博客为 有时个哥 原创,如需转载请标明出处:

最近手头的活不是很紧,所以有空整理一下

来电录音或去电录音

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

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

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

import com.example.recorderdemo.listener.TelListener;

public class TelService extends Service {
	TelListener telListener;
	TelephonyManager manager;
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		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() {
		System.out.println("销毁了。。。。。。。。。。。。。。。。。。。。。。。。。。。====------》》》》》》");
		telListener.setRecordState(false);
		super.onDestroy();
	}

}

然后给TelephonyManager设置上监听,后面设置PhoneStateListener.LISTEN_CALL_STATE,意思为监听来电状态的。然后我们再写监听类

package com.example.recorderdemo.listener;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;

import android.content.Context;
import android.media.MediaRecorder;
import android.os.Environment;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.example.recorderdemo.utils.MediaRecordUtil;

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:// 空闲
				System.out.println("===============CALL_STATE_IDLE==============");
				// 音频数据上传到服务器
				if (isRecording) {
					stopRecord(mediaRecorder);
					isRecording = false;
					if (!TextUtils.isEmpty(recordPath)&&isOffhooked&&isRinging) {
						isOffhooked=false;
						//这里可以写一些录完音之后的一些后学操作
						//也可以写一个回调
					}
				}
				isRinging = false;
				break;

			case TelephonyManager.CALL_STATE_RINGING:// 来电
				System.out.println("===============CALL_STATE_RINGING==============");
				isRinging = true;
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK:// 接通
				System.out.println("===============CALL_STATE_OFFHOOK==============");
				if (!isRecording&&isRinging) {
					startRecordAudio(number);
					number="";
					isRecording = true;
					isOffhooked =true;
				}
				break;
			default:
				break;
			}
		}
	}

	/**
	 * 描述:开始录音
	 */
	private void startRecordAudio(String number) {
		mediaRecorder = new MediaRecorder();
		try {
			// 存放的文件路径
			File soundFile = new File(Environment.getExternalStorageDirectory()
					.getCanonicalPath() + "/song");
			if (!soundFile.exists()) {
				try {
					soundFile.mkdirs();
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
			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);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 停止录音
	 * 
	 * @param mediaRecorder
	 */
	private void stopRecord(MediaRecorder mediaRecorder) {
		if (mediaRecorder != null) {
			new MediaRecordUtil(context).StopmediaRecorder(mediaRecorder);
		}
	}
}

这个监听是继承PhoneStateListener,里面有个方法onCallStateChanged,这个方法一直在监听电话的状态。一般来电是用到三个状态CALL_STATE_IDLE:// 空闲

CALL_STATE_RINGING:// 来电    CALL_STATE_OFFHOOK:// 接通,一般来电的电话状态的变化是   空闲-》来电-》接通-》空闲,这是其整个过程。而去电时是没有CALL_STATE_RINGING:// 来电这个状态的。

我们只要再各个状态做自己想做的事情就好了。

接下来就是录音类。录音有两种实现,MediaRecorder和AudioRecorder,这里是使用的MediaRecorder。下面是录音类,是在接通状态下执行。

package com.example.recorderdemo.utils;

import java.io.File;

import android.app.Activity;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Environment;
import android.widget.Toast;

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
			// 设置录音的来源为麦克风
			//			华为,酷派可以
			if ("xiaomi".equalsIgnoreCase(android.os.Build.BRAND)){
				mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
			}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()方法 你应该知道 是删除的意思;
			}
		}
	}
	
}

使用MediaRecorder时由于各个手机的系统定制不同,所以设置录音来源的的时候要根据不同的机型来设置不同的声音来源,由于手头只有华为和红米小米还有酷派,所以只对这几款做了测试。我觉得大多数手机把声音来源设置成MIC就可以了,不过小米的需要设置成VOICE_CALL.

然后经行 清单文件配置把一些需要的权限加上。把服务配置完成就可以了。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.recorderdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />
    <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"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.recorderdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.example.recorderdemo.service.TelService"></service>
    </application>
</manifest>

然后直接调用就可以了

package com.example.recorderdemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.example.recorderdemo.service.TelService;
import com.example.recorderdemo.utils.ToastUtils;

public class MainActivity extends Activity {

	Button button ;
	boolean isOpening = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.btn_open);
        button.setText("开启");
        button.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(MainActivity.this,TelService.class);
				if(isOpening){
					stopService(intent);
					button.setText("开启");
					isOpening = false;
					ToastUtils.toast(getApplicationContext(), "关闭录音功能", 0);
				}else{
					startService(intent);
					button.setText("关闭");
					isOpening = true;
					ToastUtils.toast(getApplicationContext(), "打开录音功能", 0);
				}
			}
		});
    }
}

 

上面由于加了一个字段,只能来电录音,要想去电也录音,只需要把TelListener里面的private boolean isRinging = false;// 来电标识这个字段去掉就可以了。

上面的例子所录的文件在sd卡的song文件夹里。