CocosCreator系列教程——用安卓原生实现录音与播放功能
正式开始这篇文章之前先啰嗦一下,写程序一定要细心细心再细心,一定要细心细心再细心,一定要细心细心再细心,重要的事说三遍,其实自己一直都写好了,但是一直不成功,发现多了一个“/”,然后不报错了,不知道为什么还是没声音,why?why?why?why?why?我一脑子黑人问号脸?后来发现手机是静音模式……好吧,我都服了我自己了。
开始正文,先来点掌声吧,??????为了写这个功能,花了我两天时间研究安卓,真是客户端什么都要会啊,终于在第二天即将下班之际完成这个功能了,首先是CocosCreator客户端代码,同样基于2.2.1版本,我注释写的挺详细的,不懂的可以关注我一波,私信我给你讲解一下,看js代码吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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用来播放录音
1 2 3 4 5 | public static String mDirString;//保存的路径 public static MediaRecorder mMediaRecorder;//录音的文件类 public static File audioFile; //录音保存的文件 public static boolean isRecoding = false;// true 表示正在录音 private static MediaPlayer mMediaPlayer; //播放录音文件 |
js端代码在onLoad的时候会调用这个方法,然后把路径传过来
1 2 3 4 5 | public static void setStorageDir(String paramString) { //设置当前录音文件路径 mDirString = paramString; Log.e("开始录音之前:", mDirString); } |
正式开始录音方法,不得不说,打印log是调式程序的最佳选择之一,通过log可以看出来哪一步出错了,然后定位到具体问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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("正在录音:", "成功"); } |
录音完成方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } } |
最后,播放录音方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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()); } } |
看一下客户端界面

全部搞定!!!!!!!!!!!!!!!!!! ( ̄▽ ̄)"
看到这么帅又这么无私的博主,确定不关注一波么 (●ˇ?ˇ●)