Вопрос или проблема
Я пытаюсь добавить поддержку Siri в мое приложение для отправки голосовых сообщений. Я реализовал INSendMessageIntentHandling
в основном целевом проекте приложения.
Похоже, что приложение доходит до записи голосового сообщения и передает моему обработчику намерений INSendMessageIntent
с аудиофайлом в приложении, но я не могу получить доступ к файлу вложения.
func handle(
intent: INSendMessageIntent,
completion: @escaping (INSendMessageIntentResponse) -> Void
) {
if let attachment = intent.attachments?.first,
let audioFile = attachment.audioMessageFile,
let fileURL = audioFile.fileURL
{
// Этот блок выполняется
// fileURL = "file:///var/mobile/tmp/SiriMessages/89F738F7-6092-439A-B4FA-2DD9A99F0EED.caf"
let result = processMessageAudio(url: fileURL)
completion(result)
return
}
// Эта строка не выполняется
completion(.init(code: .failure, userActivity: nil))
}
private func processMessageAudio(url: URL) -> INSendMessageIntentResponse {
var fileRef: ExtAudioFileRef?
if url.startAccessingSecurityScopedResource() {
logDebug("Доступ к файлу разрешен")
} else {
// Этот блок выполняется
logDebug("Доступ к файлу не разрешен")
}
defer {
url.stopAccessingSecurityScopedResource()
}
let openStatus = ExtAudioFileOpenURL(url as CFURL, &fileRef)
// openStatus равен -54 (kAudio_FilePermissionError)
return INSendMessageIntentResponse(code: .failure, userActivity: nil)
}
Я не уверен, чего мне не хватает. Похоже, что файл с аудио должен быть, и Siri показывает предварительный просмотр аудио для подтверждения.
Ответ или решение
Для доступа к аудиоданным из INSendMessageIntent
, вам нужно убедиться, что вы правильно обрабатываете доступ к защищённым ресурсам и сами аудиофайлы. Вы уже на правильном пути, но давайте разберёмся с возможными проблемами и решениями.
-
Проверка доступа к ресурсу: Вы правильно используете методы
startAccessingSecurityScopedResource()
иstopAccessingSecurityScopedResource()
. Однако возможно, что вы не обращаетесь к файлу в пределах сроков между началом и окончанием доступа. Убедитесь, что все операции с файлом происходят между этими вызовами. -
Проверка формата файла: Убедитесь, что файл имеет правильный формат и кодек для обработки. Метод
ExtAudioFileOpenURL
ожидает поддерживаемый формат, и возможно, вам нужно будет преобразовать файл или его метаданные. -
Обработка ошибок: Ваша текущая обработка ошибок ведет к завершению функции с кодом
.failure
, и это нормально, однако вам стоит логировать более подробные сообщения об ошибках, чтобы лучше понять, где именно происходит сбой.Для этого можно использовать
os_log
илиprint
, чтобы отобразить ошибку получения доступа и состояние обработки файла.
Пример исправленного кода может выглядеть так:
func handle(
intent: INSendMessageIntent,
completion: @escaping (INSendMessageIntentResponse) -> Void
) {
if let attachment = intent.attachments?.first,
let audioFile = attachment.audioMessageFile,
let fileURL = audioFile.fileURL {
// Проверяем доступ к ресурсу
if url.startAccessingSecurityScopedResource() {
logDebug("File access allowed")
let result = processMessageAudio(url: fileURL)
completion(result)
// Завершаем доступ после обработки
url.stopAccessingSecurityScopedResource()
return
} else {
logDebug("File access not allowed")
}
}
// Если доступ не предоставлен, возвращаем ошибку
completion(.init(code: .failure, userActivity: nil))
}
private func processMessageAudio(url: URL) -> INSendMessageIntentResponse {
var fileRef: ExtAudioFileRef?
// Пытаемся открыть файл
let openStatus = ExtAudioFileOpenURL(url as CFURL, &fileRef)
if openStatus != noErr {
logDebug("Error opening audio file: \(openStatus)") // Логирование ошибки
return INSendMessageIntentResponse(code: .failure, userActivity: nil)
}
// Здесь добавьте логику для работы с `fileRef`
// После завершения работы с файлом
if let fileRef = fileRef {
ExtAudioFileDispose(fileRef)
}
return INSendMessageIntentResponse(code: .success, userActivity: nil)
}
- Права на доступ: Проверьте настройки вашего проекта. Убедитесь, что в Info.plist указаны необходимые разрешения для работы с микрофоном, такими как
NSMicrophoneUsageDescription
.
Следуя этим рекомендациям и примерам, вы сможете более эффективно работать с аудиофайлами, полученными из INSendMessageIntent
. Если проблемы сохраняются, рассмотрите возможность проверки наличия проблемы с доступом к файлу на более низком уровне, возможно, через отладчик или логи.