android record文件大小限制,android - Android Mediarecorder setNextOutputFile IllegalStateException - 堆栈内存溢...

博主尝试用Android MediaRecorder将录音分成多个文件,设置下一个输出文件时遇到非法状态异常。给出了代码和错误信息,经分析错误 -38 可能对应“INVALID_OPERATION”,即便按文档操作仍未解决,后续修改代码也无济于事。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我试图将我的带有android mediarecorder的录音分成多个文件,但每当我设置下一个输出文件时,我都会遇到非法状态异常。

这是代码:

private void getMediaRecorderReady(String filePath, FileDescriptor nextFile) {

bufferSize = 88200;

recorder = new MediaRecorder();

recorder.setAudioSource(MediaRecorder.AudioSource.MIC);

recorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);

recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

recorder.setAudioEncodingBitRate(64000);

recorder.setAudioSamplingRate(44100);

recorder.setAudioChannels(1);

recorder.setOutputFile(filePath);

recorder.setMaxDuration(1000);

recorder.setMaxFileSize(100000);

try {

recorder.prepare();

recorder.setNextOutputFile(nextFile);

} catch (IOException e) {

e.printStackTrace();

}

}

这是错误:

E/MediaRecorder: setNextOutputFile failed: -38

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1

Process: com.example.a49164.teachmi, PID: 31554

java.lang.RuntimeException: An error occurred while executing doInBackground()

at android.os.AsyncTask$3.done(AsyncTask.java:353)

at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)

at java.util.concurrent.FutureTask.setException(FutureTask.java:252)

at java.util.concurrent.FutureTask.run(FutureTask.java:271)

at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)

at java.lang.Thread.run(Thread.java:764)

Caused by: java.lang.IllegalStateException

at android.media.MediaRecorder._setNextOutputFile(Native Method)

at android.media.MediaRecorder.setNextOutputFile(MediaRecorder.java:878)

at com.example.a49164.teachmi.ExComThread.getMediaRecorderReady(ExComThread.java:189)

at com.example.a49164.teachmi.ExComThread.soundTransfer(ExComThread.java:211)

at com.example.a49164.teachmi.ExComThread.doInBackground(ExComThread.java:82)

at com.example.a49164.teachmi.ExComThread.doInBackground(ExComThread.java:46)

at android.os.AsyncTask$2.call(AsyncTask.java:333)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)

at java.lang.Thread.run(Thread.java:764)

因此,在进行一些挖掘之后,错误-38等于“-ENOSYS”或“INVALID_OPERATION”,如果记录器为空或准备未被调用(但我先调用prepare()),这似乎就会发生。

这是一些原生的android代码:

enum {

OK = 0, // Everything's swell.

NO_ERROR = 0, // No errors.

UNKNOWN_ERROR = 0x80000000,

NO_MEMORY = -ENOMEM,

INVALID_OPERATION = -ENOSYS,

BAD_VALUE = -EINVAL,

BAD_TYPE = 0x80000001,

NAME_NOT_FOUND = -ENOENT,

PERMISSION_DENIED = -EPERM,

NO_INIT = -ENODEV,

ALREADY_EXISTS = -EEXIST,

DEAD_OBJECT = -EPIPE,

FAILED_TRANSACTION = 0x80000002,

JPARKS_BROKE_IT = -EPIPE,

#if !defined(HAVE_MS_C_RUNTIME)

BAD_INDEX = -EOVERFLOW,

NOT_ENOUGH_DATA = -ENODATA,

WOULD_BLOCK = -EWOULDBLOCK,

TIMED_OUT = -ETIMEDOUT,

UNKNOWN_TRANSACTION = -EBADMSG,

#else

BAD_INDEX = -E2BIG,

NOT_ENOUGH_DATA = 0x80000003,

WOULD_BLOCK = 0x80000004,

TIMED_OUT = 0x80000005,

UNKNOWN_TRANSACTION = 0x80000006,

#endif

FDS_NOT_ALLOWED = 0x80000007,

};

原生nextoutputfile:

status_t MediaRecorder::setNextOutputFile(int fd)

{

ALOGV("setNextOutputFile(%d)", fd);

if (mMediaRecorder == NULL) {

ALOGE("media recorder is not initialized yet");

return INVALID_OPERATION;

}

// It appears that if an invalid file descriptor is passed through

// binder calls, the server-side of the inter-process function call

// is skipped. As a result, the check at the server-side to catch

// the invalid file descritpor never gets invoked. This is to workaround

// this issue by checking the file descriptor first before passing

// it through binder call.

int flags = fcntl(fd, F_GETFL);

if (flags == -1) {

ALOGE("Fail to get File Status Flags err: %s", strerror(errno));

}

// fd must be in read-write mode or write-only mode.

if ((flags & (O_RDWR | O_WRONLY)) == 0) {

ALOGE("File descriptor is not in read-write mode or write-only mode");

return BAD_VALUE;

}

status_t ret = mMediaRecorder->setNextOutputFile(fd);

if (OK != ret) {

ALOGE("setNextOutputFile failed: %d", ret);

}

return ret;

}

我可能错了-38确实等于-ENOSYS的事实,但是,我仍然不知道为什么它不起作用,因为我传递文件描述符并在准备之后调用它,如android文档中所述。

我非常欢迎你的帮助,谢谢!

编辑:我试图在准备后立即删除setNextOutputFile(nextFile),只保留一个:

recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {

@Override

public void onInfo(MediaRecorder mr, int infoCode, int extra) {

System.out.println("----------------------------------------onMaxFileSizeApproaching " + infoCode);

if (infoCode == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {

System.out.println("max sized reached");

String path = Environment.getExternalStorageDirectory().getPath() + "/dataSound" + currFile + ".aac";

File nextFile = new File(path);

try {

FileOutputStream fos = new FileOutputStream(nextFile);

recorder.setNextOutputFile(fos.getFD());

} catch (IOException e) {

e.printStackTrace();

}

String currPath = Environment.getExternalStorageDirectory().getPath() + "/dataSound" + (currFile - 1) + ".aac";

sendDataPath = currPath;

currFile++;

}

}

});

但无济于事......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值