iOS应用中如何将录制的语音设置为通知音效?
Hey there! I’ve seen tons of devs ask about this exact scenario—using a user-recorded voice clip as a local notification sound is totally feasible, but there are platform-specific hoops to jump through and common pitfalls to avoid. Let’s break this down step by step.
First: Record the Audio (iOS/Android Code Snippets)
First, you’ll need to capture the voice recording in your app. Here’s how to set that up for both major platforms:
iOS (Swift)
Use AVAudioRecorder to capture the clip and save it to your app’s documents directory:
var audioRecorder: AVAudioRecorder? func startRecording() { let audioFilename = getDocumentsDirectory().appendingPathComponent("customNotification.m4r") let settings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 16000, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] do { audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings) audioRecorder?.delegate = self audioRecorder?.record() } catch { print("Recording failed: \(error.localizedDescription)") } } private func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] }
Android (Kotlin)
Use MediaRecorder to capture the clip and save it to your app’s external files directory:
private var recorder: MediaRecorder? = null fun startRecording() { recorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.AAC) setOutputFile(getOutputFile().absolutePath) prepare() start() } } private fun getOutputFile(): File { val dir = getExternalFilesDir(Environment.DIRECTORY_MUSIC) return File(dir, "customNotification.mp3") }
Step 2: Ensure Your Audio Meets Platform Requirements
This is where most devs get stuck—each platform has strict rules for notification sounds:
- iOS: Must be
.m4rformat, max 30 seconds, 16kHz/22kHz sample rate, and single-channel. If you recorded in another format (like.wav), useAVAssetExportSessionto convert it to.m4rin code (snippet below). - Android: Supports
.mp3,.wav,.ogg, etc. Keep clips short (system may truncate long sounds), and store files either inres/raw/(for pre-bundled clips) or your app’s external storage (for user-recorded ones).
Quick iOS Format Conversion Snippet
func convertToM4r(inputURL: URL, outputURL: URL) { let asset = AVAsset(url: inputURL) guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else { print("Couldn't create export session") return } exportSession.outputURL = outputURL exportSession.outputFileType = .m4r exportSession.exportAsynchronously { switch exportSession.status { case .completed: print("Conversion successful!") case .failed: print("Conversion failed: \(exportSession.error?.localizedDescription ?? "Unknown error")") default: break } } }
Step 3: Attach the Sound to Your Local Notification Payload
Once your audio is properly formatted, wire it into your notification:
iOS Implementation
You can use either bundled sounds or user-recorded sounds from the documents directory:
func scheduleCustomSoundNotification() { let content = UNMutableNotificationContent() content.title = "Reminder" content.body = "Time to check in!" // Use a user-recorded sound from the documents directory let recordedSoundURL = getDocumentsDirectory().appendingPathComponent("customNotification.m4r") content.sound = UNNotificationSound(url: recordedSoundURL) // Or use a bundled sound: // content.sound = UNNotificationSound(named: UNNotificationSoundName("customNotification.m4r")) let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let request = UNNotificationRequest(identifier: "customSoundNotif", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("Failed to schedule notification: \(error.localizedDescription)") } } }
Android Implementation
You’ll need to set up a notification channel (required for Android O+) and link the sound to it:
fun scheduleCustomSoundNotification() { val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val channelId = "custom_sound_channel" // Create notification channel (Android O+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel(channelId, "Custom Sound Channel", NotificationManager.IMPORTANCE_DEFAULT).apply { setSound(getCustomSoundUri(), AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()) } notificationManager.createNotificationChannel(channel) } // Build the notification val notification = NotificationCompat.Builder(this, channelId) .setContentTitle("Reminder") .setContentText("Time to check in!") .setSmallIcon(R.drawable.ic_notification) .setSound(getCustomSoundUri()) .build() notificationManager.notify(1, notification) } private fun getCustomSoundUri(): Uri { // Option 1: User-recorded sound from external storage return Uri.fromFile(File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "customNotification.mp3")) // Option 2: Bundled sound from res/raw/ // return Uri.parse("android.resource://" + packageName + "/" + R.raw.custom_notification) }
Common Pitfalls Devs Face (And Fixes)
- iOS sound not playing: Double-check the
.m4rformat, length (<30s), and file path. If using a documents directory file, ensure the URL is correctly constructed—sometimes typos here are the culprit. - Android sound muted: Make sure your notification channel’s importance isn’t set to
IMPORTANCE_LOWorIMPORTANCE_MIN. Also, confirm you’ve grantedPOST_NOTIFICATIONS(Android 13+) andREAD_EXTERNAL_STORAGE(if using external files) permissions. - Format conversion errors: For iOS, ensure your input audio is valid and that the export session has the correct output file type set to
.m4r.
Lots of devs have worked through this before—stick to the platform rules and test early, and you’ll have your custom voice recording playing as a notification sound in no time!
内容的提问来源于stack exchange,提问作者Dheeraj Gupta

