【uniapp】uniapp安卓插件实时监听麦克风数据
·
class FyUniClientBuilder : UniModule() {
private var isRecording = false
private var audioRecord: AudioRecord? = null
private var recordBufferSize = 0
/**麦克风的实时数据*/
private val recordingLiveType = 1
/**录音结束*/
private val recordingCompleteType = 2
private var mRecordingCallback: UniJSCallback? = null
/**
* 麦克风数据监听
* */
@UniJSMethod(uiThread = false)
fun setRecordingCallback(callback: UniJSCallback) {
mRecordingCallback = callback
}
/**开始录音,录音结束后,自动发送数据给服务器*/
@UniJSMethod(uiThread = true)
fun startRecording() {
Log.i(TAG, "startRecording: 尝试开始录音")
try {
if (!canRecording()) {
requestPermission()
mJSCallback?.invoke(JSONObject().apply {
put("error", "没有录音权限")
})
return
}
if (isRecording) {
Log.w(TAG, "startRecording: 已经开始录音")
return
}
if (audioRecord == null) {
recordBufferSize = AudioRecord.getMinBufferSize(
mSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT
)
audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
mSampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
recordBufferSize
)
}
audioRecord?.startRecording() ?: error("audioRecord is null")
isRecording = true
Log.i(TAG, "startRecording: 开始录音")
createRecordFile()
} catch (e: Exception) {
if (e is InvocationTargetException) {
Log.e(TAG, "startRecording反射异常: ${e.targetException}")
e.printStackTrace()
return
}
Log.e(TAG, "startRecording异常: ", e)
}
Log.i(TAG, "startRecording: 录音线程开启")
Thread {
try {
val inFile = recordFile
Log.i(TAG, "startRecording: 开始读取麦克风数据in线程")
val buffer = ByteArray(recordBufferSize)
while (isRecording) {
val read = audioRecord?.read(buffer, 0, recordBufferSize)
?: AudioRecord.ERROR_INVALID_OPERATION
if (read != AudioRecord.ERROR_INVALID_OPERATION) {
// Log.i(
// TAG,
// "startRecording: 读取到了麦克风数据: $read, ${buffer.size},file:${inFile?.absolutePath}"
// )
mRecordingCallback?.invokeAndKeepAlive(JSONObject().apply {
put("type", recordingLiveType)
put("data", buffer)
})
inFile?.appendBytes(buffer)
}
}
val retVal = JSONObject()
retVal["type"] = recordingCompleteType
retVal["recordFilePath"] = recordFile?.absolutePath.toString()
retVal["recordFileBytes"] = recordFile?.readBytes()
retVal["recordFileLength"] = recordFile?.length()
mRecordingCallback?.invokeAndKeepAlive(retVal)
Log.i(TAG, "startRecording: 读取麦克风数据in线程结束")
} catch (e: Exception) {
Log.e(TAG, "startRecording: ", e)
}
}.start()
}
private fun createRecordFile() {
val parent = context.getExternalFilesDir(null)?.absolutePath ?: error("no path")
val recordDirPath = parent + File.separator + "record"
Log.i(TAG, "startRecording: recordDirPath: $recordDirPath")
val recordDirFile = File(recordDirPath)
if (recordDirFile.exists().not()) {
recordDirFile.mkdirs()
}
val fileName = "record_${timestampToDateString(System.currentTimeMillis())}.m4a"
Log.i(TAG, "startRecording: fileName: $fileName")
recordFile = File(recordDirPath + File.separator + fileName)
try {
if (recordFile!!.exists()) {
recordFile!!.delete()
Log.i(TAG, "startRecording: 删除文件成功,${recordFile!!.absolutePath}")
} else {
recordFile!!.createNewFile()
Log.i(TAG, "startRecording: 创建文件成功")
}
} catch (e: IOException) {
e.printStackTrace()
}
}
@UniJSMethod(uiThread = false)
fun stopRecording() {
try {
Log.i(TAG, "stopRecording: 停止录音")
isRecording = false
audioRecord?.stop()
audioRecord?.release()
audioRecord = null
try {
Thread { sendFyFileSize(recordFile!!) }.start()
} catch (e: Exception) {
Log.e(TAG, "sendFyFileSize: ", e)
}
} catch (e: Exception) {
if (e is InvocationTargetException) {
Log.e(TAG, "stopRecording反射异常: $e")
e.printStackTrace()
return
}
Log.e(TAG, "stopRecording异常: ", e)
}
}
}
在js层引入,注意 可能会提示插件存在但未打包,引用失败等云云。在确认插件的package.json class精确到Class类名,以及里面的id name需要和文件夹名一致。否则都会出现失败,如果都没问题还显示这个,上传自定义基座再多试几次。
更多推荐
所有评论(0)