CocosCreator系列——用安卓原生实现录音与播放功能
正式开始这篇文章之前先啰嗦一下,写程序一定要细心细心再细心,一定要细心细心再细心,一定要细心细心再细心,重要的事说三遍,其实自己一直都写好了,但是一直不成功,发现多了一个“/”,然后不报错了,不知道为什么还是没声音,why?why?why?why?why?我一脑子黑人问号脸?后来发现手机是静音模式……好吧,我都服了我自己了。
开始正文,先来点掌声吧,👏👏👏为了写这个功能,花了我两天时间研究安卓,真是客户端什么都要会啊,终于在第二天即将下班之际完成这个功能了,首先是CocosCreator客户端代码,同样基于2.2.1版本,我注释写的挺详细的,不懂的可以关注我一波,私信我给你讲解一下,看js代码吧:
cc.Class({
extends: cc.Component,
properties: {
luyinBtn: cc.Node,
},
// use this for initialization
onLoad: function () {
if (cc.sys.isNative) {
//设置用来存放录制语音的路径
this.setStorageDir(jsb.fileUtils.getWritablePath() + "audioS/");
}
this.luyinBtn.on(cc.Node.EventType.TOUCH_START, this.onVoiceTouch, this);//一直按着录音
this.luyinBtn.on(cc.Node.EventType.TOUCH_END, this.stopRecord, this);//擡起录音完成
this.luyinBtn.on(cc.Node.EventType.TOUCH_CANCEL, this.stopRecord, this);//擡起取消录音,暂未实现,实际项目里再说吧,这个简单
},
setStorageDir: function (dir) {
if (cc.sys.os == cc.sys.OS_ANDROID) {
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "setStorageDir", "(Ljava/lang/String;)V", dir);
}
},
onVoiceTouch() {
if (!cc.sys.isNative) {
return;
}
//开始录音啦!!!!!!!
//先清理一下旧文件
this.clearCache("record.mp3");
if (cc.sys.os == cc.sys.OS_ANDROID) {
cc.log("开始说话--------------------------------");
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "prepare", "(Ljava/lang/String;)V", "record.mp3");
}
},
stopRecord: function () {
if (!cc.sys.isNative) {
return;
}
if (cc.sys.os == cc.sys.OS_ANDROID) {
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "stopRecord", "()V");
}
},
clearCache: function (filename) {
if (cc.sys.isNative) {
var url = jsb.fileUtils.getWritablePath() + "/audioS/" + filename;
if (jsb.fileUtils.isFileExist(url)) {
jsb.fileUtils.removeFile(url);
}
if (jsb.fileUtils.isFileExist(url + ".mp3")) {
jsb.fileUtils.removeFile(url + ".mp3");
}
}
},
//点击播放的时候,调这个方法就可以了
onPlay() {
if (!cc.sys.isNative) {
return;
}
if (cc.sys.os == cc.sys.OS_ANDROID) {
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "playSound", "()V");
}
},
然后是Java代码,先初始化一下各类参数录音和播放主要依靠MediaRecorder和MediaPlayer两个类来实现,MediaRecorder用来实现录音,MediaPlayer用来播放录音
public static String mDirString;//保存的路径
public static MediaRecorder mMediaRecorder;//录音的文件类
public static File audioFile; //录音保存的文件
public static boolean isRecoding = false;// true 表示正在录音
private static MediaPlayer mMediaPlayer; //播放录音文件
js端代码在onLoad的时候会调用这个方法,然后把路径传过来
public static void setStorageDir(String paramString) {
//设置当前录音文件路径
mDirString = paramString;
Log.e("开始录音之前:", mDirString);
}
正式开始录音方法,不得不说,打印log是调式程序的最佳选择之一,通过log可以看出来哪一步出错了,然后定位到具体问题
public static void prepare(String paramString) {
File destDir = new File(mDirString);//文件保存路径
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置播放源 麦克风
Log.e("设置麦克风:", "成功");
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //设置输入格式 3gp
Log.e("设置输入格式:", "成功");
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //设置编码 AMR
Log.e("设置编码:", "成功");
if (!destDir.exists()) {
destDir.mkdirs();
}
Log.e("创建文件路径:", "成功");
try {
audioFile = new File(mDirString, paramString);
if (audioFile.exists()) {
audioFile.delete();
Log.e("删除文件路径:", "成功");
}
audioFile.createNewFile();
Log.e("创建录音文件:", "成功");
} catch (Exception e) {
throw new RuntimeException("Couldn't create recording audio file", e);
}
mMediaRecorder.setOutputFile(audioFile.getAbsolutePath());
Log.e("设置录音文件输出路径:", "成功");
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
throw new RuntimeException("IllegalStateException on MediaRecorder.prepare", e);
} catch (IOException e) {
throw new RuntimeException("IOException on MediaRecorder.prepare", e);
}
isRecoding = true;
mMediaRecorder.start();
Log.e("正在录音:", "成功");
}
录音完成方法
public static void stopRecord() {
if (isRecoding) {
if (mMediaRecorder != null) {
try {
mMediaRecorder.stop();
Log.e("录音完成:", "成功");
} catch (IllegalStateException e) {
// TODO 如果当前java状态和jni里面的状态不一致,
e.printStackTrace();
mMediaRecorder = null;
mMediaRecorder = new MediaRecorder();
}
mMediaRecorder.release();
mMediaRecorder = null;
}
}
}
最后,播放录音方法
public static void playSound(){
if(mMediaPlayer==null){
Log.e("新建播放类:", "成功");
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("mMediaPlayer错误监听null:", "错误");
mMediaPlayer.reset();
return false;
}
});
}else{
Log.e("mMediaPlayer错误监听有值:", "成功");
mMediaPlayer.reset();
}
try {
//详见“MediaPlayer”调用过程图
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
Log.e("mMediaPlayer设置类型:", "成功");
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer paramAnonymousMediaPlayer) {}
});
mMediaPlayer.setDataSource(mDirString+"/record.mp3");
Log.e("mMediaPlayer设置文件:", mDirString+"record.mp3");
mMediaPlayer.prepare();
mMediaPlayer.start();
Log.e("mMediaPlayer开始播放:", "成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("语音error==",e.getMessage());
}
}
看一下客户端界面
全部搞定!!!!!!!!!!!!!!!!!! ( ̄▽ ̄)"
看到这么帅又这么无私的博主,确定不关注一波么 (●ˇ∀ˇ●)