Kotlin Multiplatform调用AVAudioRecorder触发空指针异常排查
Kotlin Multiplatform iOS端AVAudioRecorder初始化NPE问题解决
问题场景
在Kotlin Multiplatform开发跨平台音频录制PoC时,iOS端通过Kotlin/Native封装原生AVAudioRecorder逻辑,调用构造方法时触发NullPointerException,但Swift原生实现相同逻辑却能正常工作。
触发异常的初始代码
iOS端Kotlin实现代码:
val settings = mapOf( "AVFormatIDKey" to kAudioFormatAppleIMA4, "AVSampleRateKey" to 44100.0, "AVNumberOfChannelsKey" to 2, "AVEncoderBitRateKey" to 12800, "AVLinearPCMBitDepthKey" to 16, "AVLinearPCMIsBigEndianKey" to false, "AVLinearPCMIsFloatKey" to false, ) as Map<Any?, *> val url = NSURL(fileURLWithPath = outputFile) // 打印配置与URL信息 println(settings) println("File is: ($url)") memScoped { try { val error: ObjCObjectVar<NSError?> = alloc() recorder = AVAudioRecorder(url, settings, error.ptr) recorder?.meteringEnabled = true recorder?.prepareToRecord() println(error) } catch (e: Exception) { println(e.toString()) e.printStackTrace() } }
输出的配置与URL详情:
{AVFormatIDKey=1768775988, AVSampleRateKey=44100.0, AVNumberOfChannelsKey=2, AVEncoderBitRateKey=12800, AVLinearPCMBitDepthKey=16, AVLinearPCMIsBigEndianKey=false, AVLinearPCMIsFloatKey=false} File is: (file:/Users/gazer/Library/Developer/CoreSimulator/Devices/33505695-6067-4B93-81D3-087DF397396F/data/Containers/Data/Application/A931840F-93B9-4936-AFBD-BD834BD80AF5/Documents/recording.m4a -- file:///)
outputFile由iOS原生Swift生成:
let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a") // outputFile == audioFilename.absoluteString func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let documentsDirectory = paths[0] return documentsDirectory }
异常栈信息:
at 2 shared 0x10b760779 kfun:kotlin.RuntimeException#<init>(){} + 73 (/opt/buildAgent/work/acafc8c59a79cc1/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:32:28) at 3 shared 0x10b7609b9 kfun:kotlin.NullPointerException#<init>(){} + 73 (/opt/buildAgent/work/acafc8c59a79cc1/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:43:28) at 4 shared 0x10b7862d4 ThrowNullPointerException + 132 (/opt/buildAgent/work/acafc8c59a79cc1/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt:15:11) at 5 shared 0x10b6d3aae kfun:ar.com.p39.powernotes.recorder.IOSAudioRecordThread#startRecording(){} + 2910
对比验证:Swift原生正常工作代码
用Swift实现相同逻辑并将实例传入Kotlin时可正常录制:
let settings: [String: Any] = [ AVFormatIDKey: kAudioFormatLinearPCM, AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 2, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] var url = URL(string: outputFile) do { recorder = try AVAudioRecorder(url: url!, settings: settings) recorder?.isMeteringEnabled = true recorder?.prepareToRecord() recorder?.record() catch { debugPrint("ERror") }
解决方案
问题根源在于音频配置参数不兼容,将配置改为PCM格式后异常消失,修改后的Kotlin配置如下:
val settings = mapOf( "AVFormatIDKey" to kAudioFormatLinearPCM, "AVSampleRateKey" to 1600.0, "AVNumberOfChannelsKey" to 1, "AVLinearPCMBitDepthKey" to 8, "AVLinearPCMIsBigEndianKey" to false, "AVLinearPCMIsFloatKey" to false, )
内容的提问来源于stack exchange,提问作者Ricardo Markiewicz
相关产品推荐
相关产品推荐

