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



我遇到了与这里发布的"Paul"完全相同的问题:无法通过"打开位置:";来自语音备忘录应用程序-尚未发布有关此主题的答案。

从本质上讲,我想做的很简单:在iOS上录制语音备忘录后,我选择"打开方式",并从显示的弹出窗口中选择我的应用程序。

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

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

谢谢!

经过一些实验和这篇博客文章的大量指导(http://www.theappguruz.com/blog/share-extension-in-ios-8),似乎可以使用应用程序扩展(特别是操作扩展)和应用程序组的组合来实现这一点。我将描述第一部分,它将使您能够将录音从Voice Memos获取到您的应用程序扩展。第二部分——从应用程序扩展到包含应用程序(您的"主"应用程序)的录制——可以使用应用程序组完成;请查阅上面的博客文章了解如何做到这一点。

  1. 在项目中为应用程序扩展创建一个新目标,方法是选择"文件">"新建">"目标…"。。。从Xcode的菜单。在提示您"为新目标选择模板"的对话框中:选择"操作扩展",然后单击"下一步">

注意:不要像上面的博客文章示例中那样选择"共享扩展"。这种方法更适合与其他用户共享或发布到网站。

  1. 为您的操作扩展填写"产品名称:",例如MyActionExtension。此外,对于"操作类型:",我选择了"呈现用户界面",因为Dropbox就是这样显示的。选择此选项会将视图控制器(ActionViewController)和情节提要(Maininterface.storyboard)添加到应用程序扩展中。视图控制器是一个很好的地方,可以向用户提供反馈,并在将音频文件导出到应用程序之前为用户提供重命名音频文件的机会。

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

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

  4. 生成并运行您刚刚创建的方案。系统将提示您"选择要运行的应用程序:"。从列表中选择"语音备忘录",然后单击"运行"。(你可能需要一个物理设备;我不认为模拟器上有语音备忘录。)这将在你的设备上构建和部署你的动作扩展(及其包含的应用程序)。然后在您的设备上启动"语音备忘录"。如果你现在用"语音备忘录"录制了一段录音,然后试图分享它,你应该在底部一行看到你的动作扩展(带有一个空白图标)。如果你在那里看不到,点击那一行的"更多"按钮,并将你的动作扩展开关设置为"打开"。点击你的动作扩展只会弹出一个带有"完成"按钮的空视图。模板代码会查找一个图像文件,但找不到任何图像文件。我们将在下一步中解决此问题。

  5. 编辑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。将整个override 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
}
}
}

6c。按照上一步骤构建和运行。这一次,点击操作扩展将显示与以前相同的视图控制器,但现在覆盖了包含并播放音频录制的AVPlayerViewController实例。此外,我在代码中插入的两个print()语句应该给出如下输出:

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"
)}
  1. 对操作扩展名的Info.plist文件进行以下更改:

7a。Bundle display name默认为您赋予操作扩展名的任何名称(本例中为MyActionExtension)。您可能希望将其更改为Save to MyApp。(相比之下,Dropbox使用Save to Dropbox。)

7b。为关键字CFBundleIconFile插入一行,并将其设置为TypeString(第2列),然后将其值设置为MyActionIcon或类似的值。然后,您需要提供相应的5个图标文件。在我们的示例中,这些将是:MyActionIcon.pngMyActionIcon@2x.pngMyActionIcon@3x.pngMyActionIcon~ipad.pngMyActionIcon@2x~ipad.png。(这些图标对于iphone应该是60x60点,对于ipad应该是76x76点。只有alpha通道用于确定哪些像素是灰色的,RGB通道被忽略。)将这些图标文件添加到应用程序扩展的捆绑包中,而不是包含应用程序的捆绑包。

7c。在某个时刻,您需要将关键字NSExtension > NSExtensionAttributes > NSExtensionActivationRule的值设置为TRUEPREDICATE以外的值。如果您希望只为音频文件而不是视频文件、pdf文件等激活操作扩展,则可以在此处指定这样的谓词。

以上内容负责将语音备忘录中的音频录制到您的应用程序扩展中。以下是如何将音频录制从应用程序扩展程序获取到包含的应用程序的概述。(如果时间允许,我稍后会充实它。)http://www.theappguruz.com/blog/ios8-app-groups)也可能有用。

  1. 设置应用程序以使用应用程序组。打开项目导航器(Cmd-0)并单击第一行以显示您的项目和目标。选择应用程序的目标,单击"功能"选项卡,查找应用程序组功能,并将其开关设置为"打开"。添加各种权利后,单击"+"号添加您的应用程序组,并将其命名为group.com.mycompany.myapp.sharedcontainer。(它必须以group.开头,并且可能应该使用某种形式的反向DNS命名。)

  2. 对应用程序扩展的目标重复上述操作,使其与上述名称相同(group.com.mycompany.myapp.sharedcontainer)。

  3. 现在,您可以从应用程序扩展端将音频录制的url写入应用程序组的共享容器。在ActionViewController.swift中,用以下内容替换实例化并呈现AVPlayerViewController的代码片段:

    let sharedContainerDefaults = NSUserDefaults.init(suiteName:
    "group.com.mycompany.myapp.sharedcontainer")  // must match the name chosen above
    sharedContainerDefaults?.setURL(audioURL, forKey: "SharedAudioURLKey")
    sharedContainerDefaults?.synchronize()
    
  4. 类似地,您可以使用以下内容从包含应用程序的一侧读取音频录制的url:

    let sharedContainerDefaults = NSUserDefaults.init(suiteName:
    "group.com.mycompany.myapp.sharedcontainer")  // must match the name chosen above
    let audioURL :NSURL? = sharedContainerDefaults?.URLForKey("SharedAudioURLKey")
    
  5. 从这里,您可以将音频文件复制到应用程序的沙盒中,例如,应用程序的Documents目录或应用程序的NSTemporaryDiretory()。阅读此博客文章(http://www.atomicbird.com/blog/sharing-with-app-extensions),了解如何使用CCD_ 28以协调的方式实现这一点。

参考文献:

创建应用程序扩展

与包含应用程序共享数据

最新更新