1.首先是录音器的启动
录音器的在启动的时候,需要判断这个启动意图来自于哪里?
一般是两种,来自于lauchner和其他应用。
启动意图来自于launcher,就是说在桌面点击了这个录音器的图标,然后进入录音器应用,这一种是正常启动;
另一种启动意图来自于其他应用,比如,短信应用中,需要发送一条录音给对方,那它就会跳转到录音器进行录音,在跳转的时候可能会携带两个参数,一个是录音文件的格式,一个是录音文件的最大大小;这个录音文件的格式,会影响录音文件的质量以及可录音空间的大小;因为我们会根据传递进来的录音文件的格式来设置MediaRecorder的编码比特率,比特率越高,音质就越好,但是录音文件的内存就越大;而传递进来的录音文件的最大大小就是限制录音文件的大小的;
2.服务的开启与绑定
录音应用启动以后,会启动service以及绑定服务,启动服务是为了可以让服务再后台运行,绑定服务是为了activity可以和servcie进行交互;如果启动service或者绑定服务有一个失败,录音器都会退出;
应用框架是一个MVC的模式,servcie处于C层,并且处理一些数据逻辑;
3.点击录音时
在录音之前会有三种判断
一种是当前状态的判断,如当前是否在正在录音,是否暂停录音,是否是录音播放状态或者是录音播放暂停状态,如果是正在录音就不处理,如果是录音暂停,就去继续录音,如果是录音播放或者播放暂停,那就停止播放;
一种是对内存的判断,此时如果没有内存卡或者内存已满的话,无法录音;
另一种是获得焦点,避免其他音源影响录音效果,如果获得焦点失败,无法录音;
录音开始前的最后一个步骤是创建录音文件夹,文件夹名可以自己设置;
配置MediaRecorder的参数,最后通过MediaRecorder.start()方法开始录音;
4.录音进行时:
录音进行时,会有很多意外发生,需要处理
①录音文件被意外删除,移动;
使用FileObserver监听录音文件的状态,当录音文件被删除,移动或者属性被修改时,重新设置,即录音停止,并删除正在录音的文件;
②内存不足,导致无法录音;
③activity意外被进程杀死
④audioforce被其他应用抢占;
⑤T卡被卸载
监听Intent.ACTION_MEDIA_UNMOUNTED广播,停止录音或者播放,删除录音文件,恢复状态;
⑦关机
监听广播Intent.ACTION_SHUTDOWN,保存MedioRecorder的相关配置;
⑧耳机线点击暂停按钮
监听com.android.music.musicservicecommand广播,停止录音或者播放录音,并保存录音;
录音过程中还需要动态显示录音时间,可录音时间以及音量图;
录音时需要向状态栏发送通知;
5.录音的保存
如果出现同名文件,首先需要将ContentProvider中的同名文件删除;
然后将录音文件的路径以及其他信息插入ContentProvider,并且插入到播放列表中;
如果其他应用的请求录音,还需要返回一个Uri给对方;
清除notication
6.录音列表的加载
7.录音列表的删除
8.录音的播放以及滑动到指定位置
后台录音,短信跳转到录音器怎么办
activity与service通过ServiceConnection进行交互;
MedioRecorder的参数配置,如格式选择,模式选择,音效单选,音效多选,这些都是对话框
1.oncreate()
判断activity的启动意图来自于哪里?
有三种情况:
①来自于launcher;
②来自于其他应用,比如短信界面想要添加一个录音文件,此时会跳转到录音器界面;
③来自于本身,比如录音列表界面跳转过来的;
如果是来自于其他应用,并且携带了录音类型的话,需要判断此类型是否合法,如果不合法的话,activity需要finish;
private boolean initFromIntent() {
LogUtils.i(TAG, "<initFromIntent> start");
//获取意图
Intent intent = getIntent();
if (null != intent) {
LogUtils.i(TAG, "<initFromIntent> Intent is " + intent.toString());
/**
* M: check if SoundRecorder is start by launcher or start by
* SoundRecorderServicef
*/
if(intent.getAction() == null ){
mRunFromLauncher = true ;
}else{
mRunFromLauncher = (intent.getAction().equals(INTENT_ACTION_MAIN))
|| (intent.getAction().equals("com.android.soundrecorder.SoundRecorder"));
}
String typeString = intent.getType();
if (null != typeString) {
if (RecordParamsSetting.isAvailableRequestType(typeString)) {
mRequestedType = typeString;
} else {
LogUtils.i(TAG, "<initFromIntent> return false");
return false;
}
}
mMaxFileSize = intent.getLongExtra(EXTRA_MAX_BYTES, MAX_FILE_SIZE_NULL);
/** M: if mMaxFileSize != -1, set mHasFileSizeLimitation as true. */
mHasFileSizeLimitation = (mMaxFileSize != MAX_FILE_SIZE_NULL);
}
LogUtils.i(TAG, "<initFromIntent> end");
return true;
}
2.onResume()
这里面是用来开启服务和绑定服务SoundRecorderService,如果start和bind有一个不成功的话,activity都会finish;
3.onPause()
如果此时 !mRunFromLauncher ,即是其他应用的跳转过来的,如果是正在录音的话,就停止录音,如果文件需要保存的话,就去保存;
4.onStop()
点击back键时,如果当前正在录音,需要停止录音,并且保存;如果是等待保存状态的话,就立即保存;
onClickRecordButton,交由service去处理;
录音之前有两个判断:
一个是状态的判断,如当前的状态是否是正在录音,暂停录音,正在播放录音和或者播放暂停;
如果是正在录音的话,不做处理;
如果是暂停录音的话,判断此时需要获取audiofocus,此时若audiofocus获取失败或者继续录音失败,便会放弃自己的audiofocus;
如果是正在播放录音或者是录音播放暂停,那就停止播放;
二是对设备的判断
如果此时没有安装内存卡,或者内存已满,不予录音;
如果此时获取audiofocus失败,不许录音;
获取audiofocus成功,但是录音失败,需要放弃自己的audiofocus;
在录音过程时,需要对这个录音文件进行监听,使用的是FileObserver;
录音之前需要创建录音文件,先创建一个符合要求的文件夹
录音的时候,需要获取录音类型,录音品质,模式和音效,请求类型由其他应用来提供,音效暂时没实现,是一个假的功能,录音音质有高,标准和低,它主要是与编码比特率有关系;
品质的主要不同是指录音编码比特率的不同:
public static final int ENCODE_BITRATE_AMR = 12200;
public static final int ENCODE_BITRATE_3GPP = 12200;
public static final int ENCODE_BITRATE_AWB = 28500;
public static final int HIGH_ENCODE_BITRATE_AAC = 128000;
//add for standard aac encoder
public static final int STANDARD_ENCODE_BITRATE_AAC = 48000;
public static final int ENCODE_BITRATE_VORBIS = 128000;
public static final int HIGH_SAMPLE_RATE_AAC = 48000;
//add for standard aac encoder
public static final int STANDSARD_SAMPLE_RATE_AAC = 32000;
public static final int SAMPLE_RATE_AWB = 16000;
public static final int SAMPLE_RATE_AMR = 8000;
public static final int SAMPLE_RATE_VORBIS = 48000;
创建一个RecordParams来保存这些属性参数,
如果音频类型无限制的话,即"*/*"和"audio/*"
下面是请求类型:
public static final String NOT_LIMIT_TYPE = "*/*";
public static final String AUDIO_NOT_LIMIT_TYPE = "audio/*";
public static final String AUDIO_3GPP = "audio/3gpp";
public static final String AUDIO_VORBIS = "audio/vorbis";
public static final String AUDIO_AMR = "audio/amr";
public static final String AUDIO_AWB = "audio/awb";
public static final String AUDIO_OGG = "application/ogg";
public static final String AUDIO_AAC = "audio/aac";