MediaRecorder Android 11 启动失败 -1004
MediaRecorder Android 11 start failed -1004
在 Android 11 我的 MediaRecorder 初始化失败。我怀疑问题与 scopedstorage 有关,但我一直无法找出原因。我正在使用 MediaRecorder 从麦克风录制音频。我从音频中提取振幅,所以我无意保留文件,所以路径是/dev/null
var mRecorder: MediaRecorder? = null
if (mRecorder == null) {
mRecorder = MediaRecorder()
mRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC)
mRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
mRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mRecorder!!.setOutputFile("/dev/null")
try {
mRecorder!!.prepare()
} catch (ioe: IOException) {
Log.e("[Monkey]", "IOException: " + Log.getStackTraceString(ioe))
} catch (e: SecurityException) {
Log.e("[Monkey]", "SecurityException: " + Log.getStackTraceString(e))
}
try {
mRecorder!!.start()
} catch (e: SecurityException) {
Log.e("[Monkey]", "SecurityException: " + Log.getStackTraceString(e))
}
崩溃发生在 MediaRecorded.start()。 /dev/null 不是 Android 11 上的有效路径吗?
Logcat:
start failed: -1004
2020-11-15 10:51:41.827 11836-11836/= E/AndroidRuntime: FATAL EXCEPTION: main
Process: c=, PID: 11836
java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)
将“/dev/null”替换为正确的文件路径“${externalCacheDir.absolutePath}/test.3gp”,它应该可以工作。
出于某种原因,设置 "/dev/null" 路径以防止 MediaRecorder 存储导致 Android 11 版本崩溃,截至目前,设置它得到固定的实际路径就像另一个答案中提到的那样,但在我的情况下,我在我的应用程序中需要的只是注册来自麦克风的幅度水平,所以为了防止不确定地存储在输出文件中我刷新了每分钟 MediaRecorder 对象。
这是一个完整但简化的示例:
class MainActivity : AppCompatActivity() {
private lateinit var mediaRecorder: MediaRecorder
private var handler: Handler = Handler()
private var fakeOutput = ""
private var needsFlush = false
private var flushCounter = 300
private val runnable = object : Runnable {
override fun run() {
Log.d("AudioAmplitude: ", mediaRecorder.maxAmplitude.toString())
if (needsFlush) {
if (flushCounter == 0) {
mediaRecorder.stop()
mediaRecorder.release()
initMediaRecorder()
flushCounter = 300
}
flushCounter--
}
handler.postDelayed(this, 200)
}
}
private val requestedPermissions = arrayOf(
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
requestedPermissions.forEach {
ContextCompat.checkSelfPermission(
this,
it
)
}
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED
) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
(this as Activity?)!!,
Manifest.permission.RECORD_AUDIO
)
) {
} else {
ActivityCompat.requestPermissions(
(this as Activity?)!!, arrayOf(Manifest.permission.RECORD_AUDIO),
0
)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
fakeOutput = "${externalCacheDir?.absolutePath}/temp.3gp"
needsFlush = true
} else {
fakeOutput = "/dev/null"
}
initMediaRecorder()
}
private fun initMediaRecorder() {
mediaRecorder = MediaRecorder().apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
setOutputFile(fakeOutput)
prepare()
start()
}
}
@RequiresApi(Build.VERSION_CODES.N)
override fun onResume() {
super.onResume()
mediaRecorder.resume()
handler.post(runnable)
}
@RequiresApi(Build.VERSION_CODES.N)
override fun onPause() {
super.onPause()
mediaRecorder.pause()
handler.removeCallbacks(runnable)
}
}
请注意,我使用处理程序(可能不是最佳做法)打印出 maxAmplitude,这是我从事此工作的主要原因,我正在使用它来每 60 秒刷新一次(处理程序每 200 毫秒调用一次计数器,计数器为 300 减一)。
在 Android 11 我的 MediaRecorder 初始化失败。我怀疑问题与 scopedstorage 有关,但我一直无法找出原因。我正在使用 MediaRecorder 从麦克风录制音频。我从音频中提取振幅,所以我无意保留文件,所以路径是/dev/null
var mRecorder: MediaRecorder? = null
if (mRecorder == null) {
mRecorder = MediaRecorder()
mRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC)
mRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
mRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mRecorder!!.setOutputFile("/dev/null")
try {
mRecorder!!.prepare()
} catch (ioe: IOException) {
Log.e("[Monkey]", "IOException: " + Log.getStackTraceString(ioe))
} catch (e: SecurityException) {
Log.e("[Monkey]", "SecurityException: " + Log.getStackTraceString(e))
}
try {
mRecorder!!.start()
} catch (e: SecurityException) {
Log.e("[Monkey]", "SecurityException: " + Log.getStackTraceString(e))
}
崩溃发生在 MediaRecorded.start()。 /dev/null 不是 Android 11 上的有效路径吗?
Logcat:
start failed: -1004
2020-11-15 10:51:41.827 11836-11836/= E/AndroidRuntime: FATAL EXCEPTION: main
Process: c=, PID: 11836
java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)
将“/dev/null”替换为正确的文件路径“${externalCacheDir.absolutePath}/test.3gp”,它应该可以工作。
出于某种原因,设置 "/dev/null" 路径以防止 MediaRecorder 存储导致 Android 11 版本崩溃,截至目前,设置它得到固定的实际路径就像另一个答案中提到的那样,但在我的情况下,我在我的应用程序中需要的只是注册来自麦克风的幅度水平,所以为了防止不确定地存储在输出文件中我刷新了每分钟 MediaRecorder 对象。
这是一个完整但简化的示例:
class MainActivity : AppCompatActivity() {
private lateinit var mediaRecorder: MediaRecorder
private var handler: Handler = Handler()
private var fakeOutput = ""
private var needsFlush = false
private var flushCounter = 300
private val runnable = object : Runnable {
override fun run() {
Log.d("AudioAmplitude: ", mediaRecorder.maxAmplitude.toString())
if (needsFlush) {
if (flushCounter == 0) {
mediaRecorder.stop()
mediaRecorder.release()
initMediaRecorder()
flushCounter = 300
}
flushCounter--
}
handler.postDelayed(this, 200)
}
}
private val requestedPermissions = arrayOf(
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
requestedPermissions.forEach {
ContextCompat.checkSelfPermission(
this,
it
)
}
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED
) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
(this as Activity?)!!,
Manifest.permission.RECORD_AUDIO
)
) {
} else {
ActivityCompat.requestPermissions(
(this as Activity?)!!, arrayOf(Manifest.permission.RECORD_AUDIO),
0
)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
fakeOutput = "${externalCacheDir?.absolutePath}/temp.3gp"
needsFlush = true
} else {
fakeOutput = "/dev/null"
}
initMediaRecorder()
}
private fun initMediaRecorder() {
mediaRecorder = MediaRecorder().apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
setOutputFile(fakeOutput)
prepare()
start()
}
}
@RequiresApi(Build.VERSION_CODES.N)
override fun onResume() {
super.onResume()
mediaRecorder.resume()
handler.post(runnable)
}
@RequiresApi(Build.VERSION_CODES.N)
override fun onPause() {
super.onPause()
mediaRecorder.pause()
handler.removeCallbacks(runnable)
}
}
请注意,我使用处理程序(可能不是最佳做法)打印出 maxAmplitude,这是我从事此工作的主要原因,我正在使用它来每 60 秒刷新一次(处理程序每 200 毫秒调用一次计数器,计数器为 300 减一)。