团队-手机便签-开发文档
Posted 刘铭阿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了团队-手机便签-开发文档相关的知识,希望对你有一定的参考价值。
项目托管平台地址:https://github.com/Vcandoit/Notepad.git
由于我们是团队的开发,我们写完直接就把代码发给队员了,我们有人负责的代码的合并,所以我们直接把代码进行合并去处理了
所以我就没写自己的托管平台,我们团队都发布在一个人的托管平台中了。
我负责的是录音功能木块的开发,
首先,我先设计了一下录音ui把需要的什么的编写搭建完成
下面我说一下用法:
首先我们点击按住说话,注意说话的时间要超过三秒,因为我在程序中进行了判断,低于三秒的语音我们不进行保存,会提示你录音失败,
然后当你按下按住说话的按钮后,你会发现字变成正在录音的字,那么你就可以进行录制了,当你录制完成后会提示你录音成功,多少秒。
最后点击播放按钮你就可以听到你的录音了。
开发功能实现过程:
首先我要对权限进行获取,添加麦克风的权限,6.0以上的版本要使用程序获得麦克风的使用权限
然后我进行录音机的编写,首先我要对音频进行获取,然后将录取的音频文件保存到本地的私有目录中,然后点击播放按钮在从私有目录中获取音频文件进行播放。
package com.example.apple.tuandui;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by Apple on 2017/10/25.
*/
public class RadioActivity extends AppCompatActivity {
@BindView(R.id.anjian_btn)
Button anjian_btn;
@BindView(R.id.text)
TextView text;
//多线程后台处理
private ExecutorService mExecutorService;
private MediaRecorder mMediaRecorder;
private File mAudioFile;
private long mStartRecordTime, mStopRecordTime;
private Handler mMainThreadHandler;//主线程
//主线程和后台播放线程数据同步
private volatile boolean mIsPlaying;
private MediaPlayer mMediaPlayer;
private ImageButton back_btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_radio);
back_btn = (ImageButton)findViewById(R.id.fanhui);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED)
{
//
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
1);
}
ButterKnife.bind(this);
//录音jni函数不具备线程安全性,所以调用单线程
mExecutorService = Executors.newSingleThreadExecutor();
mMainThreadHandler = new Handler(Looper.getMainLooper());
//按下说话,释放发送所以我们不要onClickListener
anjian_btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//根据不同的touch action,执行不同的逻辑
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
startRecord();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
stopRecord();
break;
default:
break;
}
//处理了touch事件,返回true
return true;
}
});
}
//利用butterknife简化代码
@OnClick(R.id.play_btn)
public void play(){
//检查当前状态,防止重复播放
if(mAudioFile!=null&&!mIsPlaying){
//设置当前播放状态
mIsPlaying = true;
//提交后台任务,开始播放
mExecutorService.submit(new Runnable() {
@Override
public void run() {
doPlay(mAudioFile);
}
});
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//activity销毁时,停止后台任务,避免内存泄漏
mExecutorService.shutdownNow();
releaseRecorder();
stopPlay();
}
/***
*
* 开始录音
*/
private void startRecord() {
//改变UI状态
anjian_btn.setText("正在说话");
//anjian_btn.setBackgroundResource();
//提交后台任务,执行录音逻辑
mExecutorService.submit(new Runnable() {
@Override
public void run() {
//释放之前录音的MediaRecorder
releaseRecorder();
//执行录音逻辑,如果失败提示用户
if (!doStart()) {
recordFail();
}
}
});
}
/***
*
* 停止录音
*/
private void stopRecord() {
//改变UI状态
anjian_btn.setText("按住说话");
//anjian_btn.setBackgroundResource();
//提交后台任务,执行停止逻辑
mExecutorService.submit(new Runnable() {
@Override
public void run() {
//执行停止录音逻辑,失败需要提醒用户
if (!doStop()) {
recordFail();
}
//释放MediaRecorder
releaseRecorder();
}
});
}
/**
* 启动录音逻辑
*/
private boolean doStart() {
try {
//创建MediaRecorder
mMediaRecorder = new MediaRecorder();
//创建录音文件
//获取绝对路径
mAudioFile = new File(getExternalFilesDir(null).getAbsolutePath() +
"/liuming/" + System.currentTimeMillis() + ".m4a");
// mAudioFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +alStorageDirectory().getAbsolutePath() +
// "/liuming/" + System.currentTimeMillis() + ".m4a");
mAudioFile.getParentFile().mkdirs();
mAudioFile.createNewFile();
//配置MediaRecorder
//(1)//从麦克风采集
mMediaRecorder.setAudiosource(MediaRecorder.AudioSource.MIC);
//(2)保存文件为MP4格式
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//(3)所有android系统都支持的采样频率
mMediaRecorder.setAudioSamplingRate(44100);
//通用的AAC编码格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//音质比较好的一个频率
mMediaRecorder.setAudioEncodingBitRate(96000);
//设为文件保存位置
mMediaRecorder.setOutputFile(mAudioFile.getAbsolutePath());
//开始录音
mMediaRecorder.prepare();//准备
mMediaRecorder.start();//开始
//记录开始录音的时间,用于统计时长
mStartRecordTime = System.currentTimeMillis();
} catch (IOException | RuntimeException e) {
e.printStackTrace();
//捕获异常,避免闪退,返回false提醒用户失败
return false;
}
//录音成功
return true;
}
/**
* 停止录音逻辑
*/
private boolean doStop() {
try {
//停止录音
mMediaRecorder.stop();
//记录停止时间,统计时长
mStopRecordTime = System.currentTimeMillis();
//只接受超过三秒的录音,在ui上显示出来
final int second = (int) ((mStopRecordTime - mStartRecordTime) / 1000);
if (second > 3) {
//text.setText(text.getText() + "\\n录音成功" + second + "秒");
//在主线程改ui,显示出来
mMainThreadHandler. post(new Runnable() {
@Override
public void run() {
text.setText(text.getText()+"\\n录音成功"+second+"秒");
}
});
}
} catch (RuntimeException e) {
e.printStackTrace();
//捕获异常,避免闪退,返回false提醒用户失败
return false;
}
//停止成功
return true;
}
/**
* 释放MediaRecorder
*/
private void releaseRecorder() {
//检查MediaRecorder不为null,
if (mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
}
}
/**
* 录音错误处理
*/
private void recordFail() {
mAudioFile = null;
//给用户Toast提示失败,要在主线程执行
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(RadioActivity.this, "录音失败", Toast.LENGTH_SHORT).show();
}
});
}
/**
* 实现播放逻辑
* @param audioFile
*/
private void doPlay(File audioFile) {
//配置播放器MediaPlayer
mMediaPlayer = new MediaPlayer();
try {
//设置声音文件
mMediaPlayer.setDataSource(audioFile.getAbsolutePath());
//设置监听回调。
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//播放结束,释放播放器
stopPlay();
}
});
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
//提示用户
playFail();
//释放播放器
stopPlay();
//错误已经处理,返回true
return true;
}
});
//设置音量,是否循环
mMediaPlayer.setVolume(1,1);//,1,1左右声道
mMediaPlayer.setLooping(false);//不需要重复播放
// 准备,开始
mMediaPlayer.prepare();
mMediaPlayer.start();
}catch (RuntimeException | IOException e){
//异常处理,防止闪退
e.printStackTrace();
//提醒用户
playFail();
//释放播放器
stopPlay();
}
}
/**
*
* 停止播放逻辑
*/
private void stopPlay() {
//重置播放状态
mIsPlaying = false;
//释放播放器
if(mMediaPlayer!=null){
//设置监听器,防止内存泄漏
mMediaPlayer.setOnCompletionListener(null);
mMediaPlayer.setOnErrorListener(null);
mMediaPlayer.stop();
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
/**
*
*提醒用户播放失败
*/
private void playFail() {
//在主线程Toast提示用户失败
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(RadioActivity.this,"播放失败",Toast.LENGTH_LONG).show();
}
});
}
public void back(View view){
startActivity(new Intent(this,MainActivity.class));
}
}
以上是关于团队-手机便签-开发文档的主要内容,如果未能解决你的问题,请参考以下文章