Ios 通过语音备忘录应用程序中的“打开位置:”导出音频文件

Ios 通过语音备忘录应用程序中的“打开位置:”导出音频文件,ios,xcode,Ios,Xcode,我的问题与保罗在这里发布的问题完全相同:-还没有关于这个主题的答案发布 基本上,我想做的很简单: 在iOS上录制语音备忘录后,我选择Open With,并从弹出窗口中选择我希望能够选择我的应用程序 我尝试了我能想到的一切,并尝试了LSItemContentTypes,但没有成功 不幸的是,我没有足够的声誉来评论上面现有的帖子,我非常渴望找到一个解决方案。任何帮助都是非常感激的,即使只是为了知道它是否可行 谢谢 经过一些实验和这篇博文的大量指导,似乎可以使用应用程序扩展(特别是动作扩展和应用程序组

我的问题与保罗在这里发布的问题完全相同:-还没有关于这个主题的答案发布

基本上,我想做的很简单: 在iOS上录制语音备忘录后,我选择Open With,并从弹出窗口中选择我希望能够选择我的应用程序

我尝试了我能想到的一切,并尝试了LSItemContentTypes,但没有成功

不幸的是,我没有足够的声誉来评论上面现有的帖子,我非常渴望找到一个解决方案。任何帮助都是非常感激的,即使只是为了知道它是否可行


谢谢

经过一些实验和这篇博文的大量指导,似乎可以使用应用程序扩展(特别是动作扩展和应用程序组)的组合来实现这一点。我将介绍第一部分,它将使您能够将录音从语音备忘转到应用程序扩展。第二部分-从应用程序扩展获取包含主应用程序的应用程序的录制-可以使用应用程序组完成;请参考上面的博客文章了解如何做到这一点

通过选择文件>新建>目标,在项目中为应用程序扩展创建新目标。。。从Xcode的菜单。在提示您为新目标选择模板的对话框中:选择操作扩展,然后单击“下一步”。 注意:不要像上面的博客文章示例那样选择共享扩展名。这种方法更适合与其他用户共享或发布到网站

为您的操作扩展填写产品名称:例如MyActionExtension。另外,对于Action Type:I selected Presents User Interface,因为Dropbox似乎就是这样做的。选择此选项会将视图控制器ActionViewController和storyboard Maininterface.storyboard添加到应用程序扩展中。视图控制器是一个向用户提供反馈的好地方,可以让用户在将音频文件导出到应用程序之前有机会重命名音频文件

单击Finish。系统将提示您激活“MyActionExtension”方案?。单击“激活”,此新方案将被激活。构建它将同时构建操作扩展和包含它的应用程序

单击项目导航器Cmd-0中MyActionExtension文件夹的“公开”三角形,以显示新创建的情节提要、ActionViewController源文件和Info.plist。您需要根据需要自定义这些文件。但是现在

构建并运行刚刚创建的方案。系统将提示您选择要运行的应用:。从列表中选择语音备忘,然后单击运行。为此,您可能需要一个物理设备;我认为模拟器上没有语音备忘录。这将在您的设备上构建并部署您的操作扩展及其包含的应用程序。然后继续在设备上启动语音备忘。如果您现在使用语音备忘录进行录制,然后尝试共享,您应该会在最下面一行看到带有空白图标的操作扩展。如果您在那里看不到,请点击该行中的“更多”按钮,然后将操作扩展的开关设置为“开”。点击操作扩展只会显示一个带有“完成”按钮的空视图。模板代码查找一个图像文件,但找不到任何图像文件不会起任何作用。我们将在下一步中解决此问题

编辑ActionViewController.swift以进行以下更改:

6a。在文件顶部附近添加AVFoundation和AVKit的导入语句:

// the next two imports are only necessary because (for our sample code)
// we have chosen to present and play the audio in our app extension.
// if all we are going to be doing is handing the audio file off to the
// containing app (the usual scenario), we won't need these two frameworks
// in our app extension.
import AVFoundation
import AVKit
6b。用以下内容替换全部覆盖func viewDidLoad{…}:

override func viewDidLoad() {
  super.viewDidLoad()

  // Get the item[s] we're handling from the extension context.

  // For example, look for an image and place it into an image view.
  // Replace this with something appropriate for the type[s] your extension supports.

  print("self.extensionContext!.inputItems = (self.extensionContext!.inputItems)")

  var audioFound :Bool = false
  for inputItem: AnyObject in self.extensionContext!.inputItems {
    let extensionItem = inputItem as! NSExtensionItem
    for attachment: AnyObject in extensionItem.attachments! {
      print("attachment = \(attachment)")
      let itemProvider = attachment as! NSItemProvider
      if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMPEG4Audio as String)
        //|| itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMP3 as String)
        // the audio format(s) we expect to receive and that we can handle
      {
        itemProvider.loadItemForTypeIdentifier(kUTTypeMPEG4Audio as String,
            options: nil, completionHandler: { (audioURL, error) in
          NSOperationQueue.mainQueue().addOperationWithBlock {

            if let audioURL = audioURL as? NSURL {

              // in our sample code we just present and play the audio in our app extension
              let theAVPlayer :AVPlayer = AVPlayer(URL: audioURL)
              let theAVPlayerViewController :AVPlayerViewController = AVPlayerViewController()
              theAVPlayerViewController.player = theAVPlayer
              self.presentViewController(theAVPlayerViewController, animated: true) {
                theAVPlayerViewController.player!.play()
              }

            }
          }
        })

        audioFound = true
        break
      }
    }

    if (audioFound) {
      break  // we only handle one audio recording at a time, so stop looking for more
    }
  }
}
self.extensionContext!.inputItems = [<NSExtensionItem: 0x127d54790> - userInfo: {
    NSExtensionItemAttachmentsKey =     (
        "<NSItemProvider: 0x127d533c0> {types = (\n    \"public.file-url\",\n    \"com.apple.m4a-audio\"\n)}"
    );
}]
attachment = <NSItemProvider: 0x127d533c0> {types = (
    "public.file-url",
    "com.apple.m4a-audio"
)}
let sharedContainerDefaults = NSUserDefaults.init(suiteName:
    "group.com.mycompany.myapp.sharedcontainer")  // must match the name chosen above
sharedContainerDefaults?.setURL(audioURL, forKey: "SharedAudioURLKey")
sharedContainerDefaults?.synchronize()
6c。构建和运行与上一步相同。这一次,点击操作扩展将显示与以前相同的视图控制器,但现在覆盖了包含并播放音频录制的AVPlayerViewController实例。此外,我在代码中插入的两条print语句应该会给出如下输出:

override func viewDidLoad() {
  super.viewDidLoad()

  // Get the item[s] we're handling from the extension context.

  // For example, look for an image and place it into an image view.
  // Replace this with something appropriate for the type[s] your extension supports.

  print("self.extensionContext!.inputItems = (self.extensionContext!.inputItems)")

  var audioFound :Bool = false
  for inputItem: AnyObject in self.extensionContext!.inputItems {
    let extensionItem = inputItem as! NSExtensionItem
    for attachment: AnyObject in extensionItem.attachments! {
      print("attachment = \(attachment)")
      let itemProvider = attachment as! NSItemProvider
      if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMPEG4Audio as String)
        //|| itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMP3 as String)
        // the audio format(s) we expect to receive and that we can handle
      {
        itemProvider.loadItemForTypeIdentifier(kUTTypeMPEG4Audio as String,
            options: nil, completionHandler: { (audioURL, error) in
          NSOperationQueue.mainQueue().addOperationWithBlock {

            if let audioURL = audioURL as? NSURL {

              // in our sample code we just present and play the audio in our app extension
              let theAVPlayer :AVPlayer = AVPlayer(URL: audioURL)
              let theAVPlayerViewController :AVPlayerViewController = AVPlayerViewController()
              theAVPlayerViewController.player = theAVPlayer
              self.presentViewController(theAVPlayerViewController, animated: true) {
                theAVPlayerViewController.player!.play()
              }

            }
          }
        })

        audioFound = true
        break
      }
    }

    if (audioFound) {
      break  // we only handle one audio recording at a time, so stop looking for more
    }
  }
}
self.extensionContext!.inputItems = [<NSExtensionItem: 0x127d54790> - userInfo: {
    NSExtensionItemAttachmentsKey =     (
        "<NSItemProvider: 0x127d533c0> {types = (\n    \"public.file-url\",\n    \"com.apple.m4a-audio\"\n)}"
    );
}]
attachment = <NSItemProvider: 0x127d533c0> {types = (
    "public.file-url",
    "com.apple.m4a-audio"
)}
let sharedContainerDefaults = NSUserDefaults.init(suiteName:
    "group.com.mycompany.myapp.sharedcontainer")  // must match the name chosen above
sharedContainerDefaults?.setURL(audioURL, forKey: "SharedAudioURLKey")
sharedContainerDefaults?.synchronize()
类似地,您可以使用以下内容从包含应用程序的一侧读取音频录制的url:

let sharedContainerDefaults = NSUserDefaults.init(suiteName:
    "group.com.mycompany.myapp.sharedcontainer")  // must match the name chosen above
let audioURL :NSURL? = sharedContainerDefaults?.URLForKey("SharedAudioURLKey")
从这里,您可以将音频文件复制到应用程序的沙盒中,例如,应用程序的文档目录或应用程序的NSTemporaryDiretory。阅读这篇博客文章,了解如何使用NSFileCoordinator以协调的方式执行此操作

参考资料:


一、 我也在努力做到这一点。我已经就你上面提到的保罗的问题悬赏100分。如果你在提出这个问题后已经找到了解决方法,请在Paul的帖子中发布你的答案,并申请你的赏金。提前谢谢。我从未找到解决方案。不幸的是,我甚至不知道这是否可能。如果我找到解决办法,我会让你知道,同样,如果你找到了,请给我写信!