使用沙盒里或下载音乐自定义通知声音(以及APP间文件共享和访问ipod音乐库)

三部分内容:
  • 从其他设备导入音频文件

  • 把音频剪切成30s以及通知指定的格式

  • 设定成通知的声音

关键的第3步

iOS没法使用类似系统闹钟,要实现类似效果只能通过本地通知来模拟。本地通知有个soundName属性,用来指定通知触发时的声音。

系统有默认声音,但如果要使用自定义的音乐,看下soundName属性的文档说明:

For this property, specify the filename (including extension) of a sound resource in the app’s main bundle or UILocalNotificationDefaultSoundName to request the default system sound.

这一段其实是个坑,这里只说了声音资源放在app’s main bundle里,main bundle是啥?就是xxx.app文件的这个目录,APP自身代码是没有访问权限的,里面的文件是在APP打包的时候一起打进去的。

这就难办了,如果想从后台下载音乐来设成通知呢?从电脑传文件进来呢?

最后看到了知乎上关于网易云音乐的“音乐闹钟”的一个问题:网易云音乐的 iOS 版音乐闹钟是怎么实现的,看到文档里有写只要放到/Library/Sounds目录下就可以。试了是对的。

然后,soundName只需要提供文件名(包括扩展名)就可以了,跟在main bundle里一样。

导入音乐

两种方法:1、使用iPhone自带的音乐APP里的歌 2、使用airDrop共享或者其他APP分享

访问ipod音乐库
let mediaquery = MPMediaQuery()
        MPMusicPlayerControllerNowPlayingItemDidChangeNotification
        if let musics = mediaquery.items {
            for music in musics {
                let title = music.valueForProperty(MPMediaItemPropertyTitle) as? String
                
                if let url = music.assetURL {
                    saveNotificationSound(url,name: title,isLast: music == musics.last)
                }
            }
        }

很简单啊,music标量类型为MPMediaItem,关键是assetURL属性,有这个东西,就可以拿到音频文件了。对于Apple music下载的音乐或者在iCloud上的音乐,这个值为nil.

使用文件共享

效果就是,在其他APP里点击分享按钮(如QQ里的在其他应用里打开)后,弹出一系列APP,怎么让你的APP在里面?

在info.plist文件配置Document types字段,在里面设置可接受的类型,我的配置:

<key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>audio</string>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.audio</string>
            </array>
        </dict>
    </array>
配置截图示例

LSItemContentTypes字段对应的是文件类型的UTI(Uniform Type Identifier
),UTI有一套完整的规范,参考Apple文档UniformTypeIdentifier

这里public.audio可以接受mp3,其他的没试过。

当其他APP或airDrop传递完成,选择你的APP打开后,会调用到APPDeleagte的func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool方法,这里的url就是传递的资源的地址,只需要判断一下类型,我暂时是按结尾为mp3来判断。是需要的音频,就可以处理。

剪切音频

因为通知有限制:1、时长不大于30s 2、格式限定,实测caf m4a可以。这里使用m4a,因为我剪切的方法就能转这个类型。

/**
     剪切音乐的指定区间,并转成m4a格式,然后存储
     
     - parameter audioPath:  源文件地址
     - parameter startTime:  剪切开始时间
     - parameter endTime:    剪切结束时间
     - parameter saveDirect: 存储地址全名
     - parameter handler:    处理结果回调
     */
    func cutoffAudio(audioPath: NSURL, startTime: Int64, endTime: Int64, saveDirect:NSURL, handler: (succeed: Bool) -> Void){
        
        let audioAsset = AVURLAsset(URL: audioPath, options: nil)
        
        if let exportSession = AVAssetExportSession(asset: audioAsset, presetName: AVAssetExportPresetAppleM4A){
            
            let startTime = CMTimeMake(startTime, 1)
            let stopTime = CMTimeMake(endTime, 1)
            
            exportSession.outputURL = saveDirect
            //输出就是m4a
            exportSession.outputFileType = AVFileTypeAppleM4A
            exportSession.timeRange = CMTimeRangeFromTimeToTime(startTime, stopTime)
            
            exportSession.exportAsynchronouslyWithCompletionHandler({ 
                handler(succeed: exportSession.status == .Completed)
            })
        }
    }

稍微封装了下

写了几个类,包括demo一起放在NotificationMusic这个项目里。

1、处理音频主要使用类TFCustomNotificationSoundProcessor,它负责把ipod音乐库的音乐拷贝过来,也负责处理从其他设备共享过来的音频文件。

启动APP的时候,调用func loadSoundNames()方法,导入ipod音乐库音乐以及加载已经在声音资源目录(/Libraty/Sounds)下的音频。

然后把所有可用的声音的文件名提取出来,统一存放在soundNames属性里。

2、从其他设备接收资源,在handleURL方法里,使用tryHandleMusicURL处理就可以

3、因为加载音频本身是异步的,所以在加载完需要一个通知来提醒外界,做界面更新之类的。

dispatch_async(dispatch_get_main_queue(), { 
                    NSNotificationCenter.defaultCenter().postNotificationName(TFLoadSoundNameCompletedNotification, object: nil)
                })

注意使用这个通知来更新可用的声音。

4、注意info.plist文件里面要配置Document types,才能从其他设备或应用接收资源。

demo地址NotificationMusic

觉得ok,点个赞,github上stat下,3Q!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,834评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 合理的分配自己的时间是很重要的,有些时候我们同时忙着很多件事情结果到了最后一件都没有做好,所以不如给自己...
    孙倩阅读 207评论 0 0
  • 昨天我的TA75同学组织了红安认捐同学的见面会,由于时间冲突没有赶过去和他们一起,心里有点失落落的,毕竟大家好容易...
    风追蓝天见海洋阅读 655评论 4 4