我正在尝试播放一个.wav文件,我使用AudioRecord Class录制,来自我的Android设备上的外部存储。我有两个按钮播放/暂停和停止。我读了其他SO帖子,但我无法解决我的问题。
我的代码如下:
final MediaPlayer m = new MediaPlayer();
final Button buttonStop = (Button) mView.findViewById(R.id.btnStop);
buttonStop.setEnabled(false);
final Button buttonPlay = (Button) mView.findViewById(R.id.btnPlay);
buttonPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String fileName = getFileSelected();
Log.i("Info: ", "Play pressed");
if ( (!isPlaying && !isPaused) && (getFileSelected().endsWith(".3gp") || getFileSelected().endsWith(".wav"))) {
isPlaying = true;
isPaused = false;
try {
m.setDataSource(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName);
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("Info: ", "DataSource set");
try {
m.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.i("Info: ", "Media Player prepare");
// m.setOnPreparedListener(new OnPreparedListener() {
// @Override
// public void onPrepared(MediaPlayer mediaPlayer) {
// m.seekTo(0);
// m.start();
// }
// });
buttonPlay.setText("Pause");
Log.i("Info: ", "Button Set to Pause");
m.seekTo(0);
Log.i("Info: ", "SeektoZero");
m.start();
Log.i("Info: ", "MesiaPlayer Started");
buttonStop.setEnabled(true);
Log.i("Info: ", "Stop Button enabled");
Toast.makeText(getActivity().getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show();
m.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
isPlaying = false;
buttonPlay.setEnabled(true);
buttonPlay.setText("Play Selected Recording");
buttonStop.setEnabled(false);
}
});
}
//paused
else if (isPaused){
m.seekTo(songPos);
m.start();
buttonStop.setEnabled(true);
buttonPlay.setText("Pause");
isPaused = false;
isPlaying = true;
}
//isPlaying and not paused
else{
songPos = m.getCurrentPosition();
m.pause();
isPaused = true;
isPlaying = false;
buttonPlay.setText("Play");
buttonStop.setEnabled(false);
}
}
});
buttonStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isPlaying && !isPaused){
isPlaying = false;
isPaused = false;
m.pause();
buttonPlay.setEnabled(true);
buttonPlay.setText("Play Selected Recording");
buttonStop.setEnabled(false);
}
}
});
我的记录按钮代码:
btnStart.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
if (!isRecordingCheckButton) {
startRecording();
isRecordingCheckButton = true;
setButtonLabel(R.id.btnStart, "Stop Recording");
Toast.makeText(getActivity().getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show();
}
else{
stopRecording();
}
}
private void startRecording(){
int hasRecordAudioPermission = ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), permission.RECORD_AUDIO);
if (hasRecordAudioPermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(permission.RECORD_AUDIO)) {
showMessageOKCancel("You must give permission to write to storage.",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {permission.RECORD_AUDIO},
111);
}
});
return;
}
requestPermissions(new String[] {permission.RECORD_AUDIO},
111);
return;
}
recorder = new AudioRecord(AudioSource.VOICE_RECOGNITION,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);
int i = recorder.getState();
if(i==1)
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
writeAudioDataToFile();
}
},"AudioRecorder Thread");
recordingThread.start();
}
private void writeAudioDataToFile(){
int hasWriteFilePermission = ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteFilePermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(permission.WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel("You must give permission to write to storage.",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {permission.WRITE_EXTERNAL_STORAGE},
111);
}
});
return;
}
requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
111);
return;
}
byte data[] = new byte[bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;
try {
os = new FileOutputStream(filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int read = 0;
if(null != os){
while(isRecording){
read = recorder.read(data, 0, bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != read){
try {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Wave File
部首:
private void WriteWaveFileHeader(
FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels,
long byteRate) throws IOException {
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
在选择我刚刚录制的文件之后按下播放时出现以下错误:
07-11 02:59:56.571 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Media Player prepare
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Button Set to Pause
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Attempt to perform seekTo in wrong state: mPlayer=0x7f6521e3c0, mCurrentState=0
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: error (-38, 0)
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: SeektoZero
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: start called in state 0
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: error (-38, 0)
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: MesiaPlayer Started
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Stop Button enabled
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples I/MediaPlayer: send context aware event
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples I/MediaPlayer: sendBroadcast CONTEXT_AWARE_MUSIC_INFO - type(error) - id (261)
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Error (-38,0)
07-11 02:59:56.621 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Error (-38,0)
07-11 02:59:56.671 20450-20450/com.ibm.watson.developer_cloud.android.examples W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView)
我知道(-38,0)与州有关,但我无法修复它。相同的代码在API 19上工作正常,但是在API 23上抛出了这个错误。我在一些SO帖子上看到错误(1,-2147483648)可能是因为应用程序没有适当的权限来阅读但是,我无法解决问题。我不知道我哪里出错了,或者我是否需要为API 23添加任何内容。这可能与运行时权限相关,因为mediaPlayer从外部存储中读取文件?如果是这样,我应该在哪里申请许可。当我转移并在我的计算机上播放时,wav文件被正确录制。
更新:我使用了另一个wav文件来检查mediaRecord类和条件是否正常工作,它们是。我现在意识到问题只是应用程序正在录制和保存的文件,因为wav无法读取(但可以在计算机上正常播放)。我无法理解,因为我在API 19上以相同的方式记录而没有检查运行时权限。
更新2 :我必须在停止按钮reset
和onClickListener
上调用onCompletionListener
方法来重置数据源。
我还复制了我的计算机上的一个录制文件,并将其从2016-07-10 22:39:40_Recording.wav
重命名为blabla.wav
并将其重新放回。它打得很好。但我仍然可以阅读具有相似日期和时间名称格式的其他类型的文件。不确定问题是否仅与名称有关。
对此问题的任何帮助将不胜感激!
答案 0 :(得分:0)
我解决了这个问题。删除文件名称中的冒号解决了错误(1,-2147483648)。 MediaPlayer无法识别和读取文件。将名称更改为其他格式解决了这个问题。
错误(-38,0)与州有关,需要一段时间才能找出问题所在。 State Diagram是一个很好的帮助。以下代码有效:
final MediaPlayer m = new MediaPlayer();
final Button buttonStop = (Button) mView.findViewById(R.id.btnStop);
buttonStop.setEnabled(false);
final Button buttonPlay = (Button) mView.findViewById(R.id.btnPlay);
buttonPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String fileName = getFileSelected();
if(!fileName.endsWith(".3gp") && !fileName.endsWith(".wav")){
}
else if ( (!isPlaying && !isPaused)) {
isPlaying = true;
isPaused = false;
int hasReadFilesPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE);
if (hasReadFilesPermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(permission.READ_EXTERNAL_STORAGE)) {
showMessageOKCancel("You must give permission to read from storage.",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE},
223);
}
});
return ;
}
requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE},
223);
return ;
}
fileName = getFileSelected();
displayResult(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName);
try {
m.setDataSource(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName);
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
m.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
buttonPlay.setText("Pause");
m.seekTo(0);
m.start();
buttonStop.setEnabled(true);
Toast.makeText(getActivity().getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show();
m.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
m.reset();
isPlaying = false;
isPaused = false;
buttonPlay.setEnabled(true);
buttonPlay.setText("Play Selected Recording");
buttonStop.setEnabled(false);
}
});
}
//paused
else if (isPaused){
m.seekTo(songPos);
m.start();
buttonStop.setEnabled(true);
buttonPlay.setText("Pause");
isPaused = false;
isPlaying = true;
}
//isPlaying and not paused
else{
songPos = m.getCurrentPosition();
m.pause();
isPaused = true;
isPlaying = false;
buttonPlay.setText("Play");
buttonStop.setEnabled(false);
}
}
});