標籤:背景工作 efault nal 開始 context news img lis 左右
項目託管平台地址: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));
}
}
團隊-手機便簽-開發文檔