diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recoding.xml b/app/src/main/res/drawable/ic_recoding.xml
new file mode 100644
index 0000000..4f819bf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recoding.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recoding.xml b/app/src/main/res/drawable/ic_recoding.xml
new file mode 100644
index 0000000..4f819bf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recoding.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/layer_microphone.xml b/app/src/main/res/drawable/layer_microphone.xml
new file mode 100644
index 0000000..dceaea2
--- /dev/null
+++ b/app/src/main/res/drawable/layer_microphone.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recoding.xml b/app/src/main/res/drawable/ic_recoding.xml
new file mode 100644
index 0000000..4f819bf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recoding.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/layer_microphone.xml b/app/src/main/res/drawable/layer_microphone.xml
new file mode 100644
index 0000000..dceaea2
--- /dev/null
+++ b/app/src/main/res/drawable/layer_microphone.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_case_upload.xml b/app/src/main/res/layout/activity_case_upload.xml
index 1b94cc1..79f5967 100644
--- a/app/src/main/res/layout/activity_case_upload.xml
+++ b/app/src/main/res/layout/activity_case_upload.xml
@@ -1,6 +1,7 @@
();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recoding.xml b/app/src/main/res/drawable/ic_recoding.xml
new file mode 100644
index 0000000..4f819bf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recoding.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/layer_microphone.xml b/app/src/main/res/drawable/layer_microphone.xml
new file mode 100644
index 0000000..dceaea2
--- /dev/null
+++ b/app/src/main/res/drawable/layer_microphone.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_case_upload.xml b/app/src/main/res/layout/activity_case_upload.xml
index 1b94cc1..79f5967 100644
--- a/app/src/main/res/layout/activity_case_upload.xml
+++ b/app/src/main/res/layout/activity_case_upload.xml
@@ -1,6 +1,7 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
index 59b6341..1445603 100644
--- a/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
+++ b/app/src/main/java/com/casic/dcms/ui/CaseUploadActivity.java
@@ -7,14 +7,16 @@
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -40,6 +42,7 @@
import com.casic.dcms.mvp.view.ICaseSmallClassView;
import com.casic.dcms.mvp.view.ICaseSubmitCaseView;
import com.casic.dcms.mvp.view.IUploadFileView;
+import com.casic.dcms.utils.AudioRecodeHelper;
import com.casic.dcms.utils.ColorHelper;
import com.casic.dcms.utils.Constant;
import com.casic.dcms.utils.FileUtils;
@@ -47,12 +50,14 @@
import com.casic.dcms.utils.ItemDecorationSpace;
import com.casic.dcms.utils.OtherUtils;
import com.casic.dcms.utils.StringHelper;
+import com.casic.dcms.utils.TimeOrDateUtil;
import com.casic.dcms.utils.ToastHelper;
import com.iceteck.silicompressorr.SiliCompressor;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
@@ -73,6 +78,8 @@
ICaseLargeClassView, ICaseSmallClassView, ICaseSubmitCaseView, IUploadFileView {
private Context context = this;
+ @BindView(R.id.caseLayout)
+ LinearLayout caseLayout;
@BindView(R.id.caseClassView)
TextView caseClassView;
@BindView(R.id.caseLargeClassView)
@@ -104,8 +111,6 @@
@BindView(R.id.submitButton)
QMUIRoundButton submitButton;
- private MediaRecorder mediaRecorder;
- private File outputFile;
private CaseLargeClassPresenterImpl caseLargeClassPresenter;
private CaseSmallClassPresenterImpl caseSmallClassPresenter;
private CaseSubmitPresenterImpl caseSubmitPresenter;
@@ -125,6 +130,8 @@
private String gridId;
private UploadVideoPresenterImpl uploadVideoPresenter;
private String audioUrl, videoUrl;
+ private AudioRecodeHelper audioRecodeHelper;
+ private PopupWindow popWindow;
@Override
public int initLayoutView() {
@@ -138,7 +145,6 @@
@Override
public void initData() {
- initMediaRecorder();
largeClassBeans = new ArrayList<>();
smallClassBeans = new ArrayList<>();
caseLargeClassPresenter = new CaseLargeClassPresenterImpl(this);
@@ -159,26 +165,28 @@
selectedResultView.setLayoutManager(new GridLayoutManager(this, 2));
selectedResultView.addItemDecoration(new ItemDecorationSpace());
selectedResultView.setAdapter(imageAdapter);
- }
- /**
- * 初始化MediaRecorder
- */
- private void initMediaRecorder() {
- mediaRecorder = new MediaRecorder();
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//麦克风
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
- mediaRecorder.setAudioSamplingRate(44100);
- //设置编码
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setAudioEncodingBitRate(96000);
- outputFile = FileUtils.getOutputAudioFile();
- mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
- try {
- mediaRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- releaseMediaRecorder();
- }
+ //录音相关
+ View view = View.inflate(this, R.layout.popu_microphone, null);
+ int popWidth = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.35);
+ int popHeight = (int) (QMUIDisplayHelper.getScreenWidth(this) * 0.30);
+ popWindow = new PopupWindow(view, popWidth, popHeight, true);
+ popWindow.setAnimationStyle(R.style.PopupAnimation);
+ ImageView recodeImageView = view.findViewById(R.id.recodeImageView);
+ TextView recodeTextView = view.findViewById(R.id.recodeTextView);
+ audioRecodeHelper = new AudioRecodeHelper();
+ audioRecodeHelper.setOnAudioStatusUpdateListener(new AudioRecodeHelper.OnAudioStatusUpdateListener() {
+ @Override
+ public void onUpdate(double db, long time) {
+ recodeImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
+ recodeTextView.setText(TimeOrDateUtil.millsToTime(time));
+ }
+
+ @Override
+ public void onStop(String filePath) {
+ uploadAudioPresenter.onReadyRetrofitRequest(new File(filePath));
+ }
+ });
}
@SuppressLint("ClickableViewAccessibility")
@@ -428,37 +436,19 @@
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- //按下动画
voiceView.animate().scaleX(0.75f).scaleY(0.75f).setDuration(100).start();
- if (mediaRecorder != null) {
- mediaRecorder.start();
- playAudioView.setText("正在录音...");
- }
+ popWindow.showAtLocation(caseLayout, Gravity.CENTER, 0, 0);
+ audioRecodeHelper.startRecordAudio();
break;
case MotionEvent.ACTION_UP:
- releaseMediaRecorder();
- if (outputFile.exists()) {
- String audioPath = outputFile.getAbsolutePath();
- uploadAudioPresenter.onReadyRetrofitRequest(new File(audioPath));
- } else {
- playAudioView.setText("录音上传失败");
- playAudioView.setTextColor(Color.RED);
- }
- //松开动画
voiceView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
+ audioRecodeHelper.stopRecordAudio();//结束录音(保存录音文件)
+ popWindow.dismiss();
break;
}
return true;
}
- private void releaseMediaRecorder() {
- if (mediaRecorder != null) {
- mediaRecorder.reset();
- mediaRecorder.release();
- mediaRecorder = null;
- }
- }
-
@Override
public void obtainLargeClassData(CaseLargeClassBean largeClassBean) {
// Log.d(TAG, "obtainLargeClassData: " + gson.toJson(largeClassBean));
diff --git a/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
new file mode 100644
index 0000000..3213591
--- /dev/null
+++ b/app/src/main/java/com/casic/dcms/utils/AudioRecodeHelper.java
@@ -0,0 +1,121 @@
+package com.casic.dcms.utils;
+
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AudioRecodeHelper {
+
+ private static final String TAG = "AudioRecodeHelper";
+ private static final int MAX_LENGTH = 1000 * 60 * 5;// 最大录音时长5分钟;
+ private MediaRecorder mMediaRecorder;
+ private String filePath;
+ private OnAudioStatusUpdateListener audioStatusUpdateListener;
+ private long startTime;
+
+ /**
+ * 开始录音 使用m4a格式
+ *
+ * @return
+ */
+ public void startRecordAudio() {
+ if (mMediaRecorder == null)
+ mMediaRecorder = new MediaRecorder();
+ try {
+ /* ②setAudioSource/setVideoSource */
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
+ /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ /*
+ * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
+ * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
+ */
+ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+
+ filePath = FileUtils.getOutputAudioFile().toString();
+ /* ③准备 */
+ mMediaRecorder.setOutputFile(filePath);
+ mMediaRecorder.setMaxDuration(MAX_LENGTH);
+ mMediaRecorder.prepare();
+ /* ④开始 */
+ mMediaRecorder.start();
+ // AudioRecord audioRecord.
+ /* 获取开始时间* */
+ startTime = System.currentTimeMillis();
+ updateMicStatus();
+ } catch (IllegalStateException | IOException e) {
+ Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+ }
+ }
+
+ /**
+ * 停止录音
+ */
+ public void stopRecordAudio() {
+ if (mMediaRecorder == null)
+ return;
+ long endTime = System.currentTimeMillis();
+ try {
+ mMediaRecorder.stop();
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ audioStatusUpdateListener.onStop(filePath);
+ filePath = "";
+ } catch (RuntimeException e) {
+ mMediaRecorder.reset();
+ mMediaRecorder.release();
+ mMediaRecorder = null;
+
+ File file = new File(filePath);
+ if (file.exists())
+ file.delete();
+ filePath = "";
+ }
+ }
+
+ public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener statusUpdateListener) {
+ this.audioStatusUpdateListener = statusUpdateListener;
+ }
+
+ /**
+ * 更新麦克状态
+ */
+ private void updateMicStatus() {
+ if (mMediaRecorder != null) {
+ double ratio = mMediaRecorder.getMaxAmplitude();
+ double db;// 分贝
+ if (ratio > 1) {
+ db = 20 * Math.log10(ratio);
+ if (null != audioStatusUpdateListener) {
+ audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
+ }
+ }
+ mHandler.postDelayed(mUpdateMicStatusTimer, 100);
+ }
+ }
+
+ private Handler mHandler = new Handler();
+ private Runnable mUpdateMicStatusTimer = this::updateMicStatus;
+
+ public interface OnAudioStatusUpdateListener {
+ /**
+ * 录音中...
+ *
+ * @param db 当前声音分贝
+ * @param time 录音时长
+ */
+ void onUpdate(double db, long time);
+
+ /**
+ * 停止录音
+ *
+ * @param filePath 保存路径
+ */
+ void onStop(String filePath);
+ }
+}
diff --git a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
index 61aa9ec..fa6b3be 100644
--- a/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
+++ b/app/src/main/java/com/casic/dcms/utils/TimeOrDateUtil.java
@@ -15,6 +15,14 @@
private static final SimpleDateFormat allDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+ private static final SimpleDateFormat millsFormat = new SimpleDateFormat("mm:ss");
+
+ /**
+ * 时间戳转时间
+ */
+ public static String millsToTime(long millSeconds) {
+ return millsFormat.format(new Date(millSeconds));
+ }
/**
* 时间戳转日期
diff --git a/app/src/main/res/anim/popup_hide.xml b/app/src/main/res/anim/popup_hide.xml
new file mode 100644
index 0000000..8a98f85
--- /dev/null
+++ b/app/src/main/res/anim/popup_hide.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/popup_show.xml b/app/src/main/res/anim/popup_show.xml
new file mode 100644
index 0000000..5cb9603
--- /dev/null
+++ b/app/src/main/res/anim/popup_show.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_recode.xml b/app/src/main/res/drawable/ic_recode.xml
new file mode 100644
index 0000000..49697d8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recode.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recoding.xml b/app/src/main/res/drawable/ic_recoding.xml
new file mode 100644
index 0000000..4f819bf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recoding.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/layer_microphone.xml b/app/src/main/res/drawable/layer_microphone.xml
new file mode 100644
index 0000000..dceaea2
--- /dev/null
+++ b/app/src/main/res/drawable/layer_microphone.xml
@@ -0,0 +1,12 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_case_upload.xml b/app/src/main/res/layout/activity_case_upload.xml
index 1b94cc1..79f5967 100644
--- a/app/src/main/res/layout/activity_case_upload.xml
+++ b/app/src/main/res/layout/activity_case_upload.xml
@@ -1,6 +1,7 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 02181b6..dee8e2e 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -49,4 +49,11 @@
- stateAlwaysHidden
+
+