近来在做IM方面的内容,做完了文字聊天,现在需要做文件,图片,语音方面的交流。Tigase本身支持文件之间的互传,我试过效果,其实还不错,但是必须双方在线的情况才能传输,这就没什么卵用了。我想,这种方式也并不适合生产环境下的情况。我准备搭建一个资源服务器,或者使用第三方的资源服务器。通过上传资源对象,上传成功后,发送带有标记的消息到服务器,服务器发送消息给对方,对象通过加载网络资源的方式来实现。因为在Android或者IOS下,有写的不错的第三方网络资源的开源库。减少很多开发者的任务。好了,开始实现Android下的语音录制与播放,后期考虑是否加入视频录制与播放。
首先,最好的资料还是google developers document。没有之一,我见过写的最好的文档。 MediaRecorder ,实现记录语言与视频的功能。可以查看下面的模型图。
一般情况下,像下面这样去记录一个语音流:
//初始化 MediaRecorder recorder = new MediaRecorder(); //设置语音资源 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //设置输出格式 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //设置编码 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //设置输出文件地址 recorder.setOutputFile(PATH_NAME); //准备 recorder.prepare(); recorder.start(); // Recording is now started ... recorder.stop(); recorder.reset(); // You can reuse the object by going back to setAudioSource() step recorder.release(); // Now the object cannot be reused
可以通过注册 setOnInfoListener(OnInfoListener) 和 setOnErrorListener(OnErrorListener 来监听运行时的信息。下面来波实例。如下:
package tech.jiangtao.support.ui.view;
import android.media.MediaRecorder;
import java.io.File;
import java.io.IOException;
import tech.jiangtao.support.kit.util.FileUtil;
/**
* Class: AudioManager </br>
* Description: 语音记录实现 </br>
* Creator: kevin </br>
* Email: [email protected] </br>
* Date: 24/12/2016 3:30 PM</br>
* Update: 24/12/2016 3:30 PM </br>
**/
public classAudioManager{
private MediaRecorder mMediaRecorder;
private String mSaveFileDictionary;
private String mCurrentFilePath;
private static AudioManager mInstance;
private AudioStateListener mAudioStateListener;
private boolean isPrepared;
publicvoidsetmAudioStateListener(AudioStateListener mAudioStateListener){
this.mAudioStateListener = mAudioStateListener;
}
privateAudioManager(){}
publicstaticAudioManagergetInstance(){
if (mInstance==null){
synchronized (AudioManager.class){
if (mInstance==null){
mInstance = new AudioManager();
}
}
}
return mInstance;
}
publicvoidprepareAudio(){
isPrepared = false;
mSaveFileDictionary = FileUtil.createAudioDic();
if (mMediaRecorder==null) {
mMediaRecorder = new MediaRecorder();
}
mCurrentFilePath = FileUtil.generatedAudioFile();
mMediaRecorder.setOutputFile(FileUtil.generatedAudioFile());
//设置音频源为麦克风
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//设置音频格式
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//设置音频编码
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
isPrepared = true;
if (mAudioStateListener!=null) {
mAudioStateListener.wellPrepared();
}
} catch (IOException e) {
e.printStackTrace();
}
}
publicintgetVoiceLevel(intmaxLevel){
if (isPrepared&&mMediaRecorder!=null){
return maxLevel*mMediaRecorder.getMaxAmplitude()/32768+1;
}
return 1;
}
publicvoidrelease(){
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
}
publicvoidcancel(){
release();
if (mCurrentFilePath!=null){
File file = new File(mCurrentFilePath);
file.delete();
}
}
public interfaceAudioStateListener{
voidwellPrepared();
}
publicStringgetmCurrentFilePath(){
return mCurrentFilePath;
}
}
MediaPlayer被用来控制和播放语音和视频文件与流。官方 MediaPlayer 。有关视频相关的API,可以查看 VideoView 。原型图如下:
音视频的播放控制以状态机的方式进行管理。上面的原型图表示了MediaPlayer的生命周期以及MediaPlayer驱动模型所支持的操作。图中,有两种类型的弧。具有单个箭头头的弧表示同步方法调用,而具有双箭头头的弧表示异步方法调用。
来看一个简单的播放语音的例子:
package tech.jiangtao.support.ui.view;
import android.content.Context;
import android.media.*;
import android.media.AudioManager;
import android.net.Uri;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Class: MediaManager </br>
* Description: 语音播放功能 </br>
* Creator: kevin </br>
* Email: [email protected] </br>
* Date: 24/12/2016 5:42 PM</br>
* Update: 24/12/2016 5:42 PM </br>
**/
public classMediaManager{
private static MediaPlayer mMediaPlayer;
private static boolean isPause;
publicstaticvoidplaySound(String filePath,
MediaPlayer.OnCompletionListener onCompletionListener) {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
} else {
mMediaPlayer.reset();
}
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnCompletionListener(onCompletionListener);
try {
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
FileInputStream is = new FileInputStream(file);
mMediaPlayer.setDataSource(is.getFD());
mMediaPlayer.prepare();
mMediaPlayer.setOnPreparedListener(mp -> mMediaPlayer.start());
} catch (IOException e) {
e.printStackTrace();
}
}
publicstaticvoidpause(){
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
isPause = true;
}
}
publicstaticvoidresume(){
if (mMediaPlayer != null && isPause) {
mMediaPlayer.start();
isPause = false;
}
}
publicstaticvoidrelease(){
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
文章只是对语音的录制与播放做了一个简单的记录。以备以后查看。具体的每一个环节的意义,调用方式等等。查看官方文档。