How to detect if an MPMediaItem represents a DRM-protected audio track on iOS

老子叫甜甜 提交于 2019-11-27 08:19:38

Here's how I do it:

MPMediaItem* item;

NSURL* assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSString *title=[item valueForProperty:MPMediaItemPropertyTitle];

if (!assetURL) {
    /*
     * !!!: When MPMediaItemPropertyAssetURL is nil, it typically means the file
     * in question is protected by DRM. (old m4p files)
     */
    NSLog(@"%@ has DRM",title);
}

Since iOS 4.2 there is a way. There may be a more effective way then the example here (but for my app I needed to create AVPlayerItems anyway).

MPMediaItem item;
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVPlayerItem *avItem = [[AVPlayerItem alloc] initWithURL:assetURL];
BOOL fairplayed = avItem.asset.hasProtectedContent;
Josip B.

From iOS 4.2 the AVAsset class has a property hasProtectedContent so you can check:

NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVAsset *asset = [AVAsset assetWithURL:assetURL];

if ([asset hasProtectedContent] == NO) {..do your stuff..}

MPMediaItemPropertyAssetURL is not nil on iPhone X running iOS 11 for songs saved offline via Apple Music but AVPlayer is unable to play them since they are DRM protected. The same song returns MPMediaItemPropertyAssetURL nil on iOS 9.

MPMediaItemPropertyAssetURL returns nil for songs added to Library via Apple Music but not available offline - both on iOS 9 & 11.

Thus, @voidStern's answer (and not Justin Kent's) is the correct way to test for DRM-protected asset.

Swift 4 version of voidStern's answer (works perfectly for me on iOS 9 to 11):

let itemUrl = targetMPMediaItem?.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
if itemUrl != nil {
    let theAsset = AVAsset(url: itemUrl!)
    if theAsset.hasProtectedContent {
        //Asset is protected
        //Must be played only via MPPlayer
    } else {
        //Asset is not protected
        //Can be played both via AVPlayer & MPPlayer\
    }
} else {
    //probably the asset is not avilable offline
    //Must be played only via MPPlayer
}

Another correct way of checking for DRM-protected asset is by making use of protectedAsset property of MPMediaItem - an answer by @weirdyu. But, this property is available only on iOS 9.2 and above.

Swift 4 solution for this method (works perfectly for me on iOS 9.2 and above):

if #available(iOS 9.2, *) {
    if (targetMPMediaItem?.hasProtectedAsset)! {
        //asset is protected
        //Must be played only via MPMusicPlayer
    } else {
        //asset is not protected
        //Can be played both via AVPlayer & MPMusicPlayer
    }
} else {
    //Fallback on earlier versions
    //Probably use the method explained earlier
}

iOS9.2+: Please use MPMediaItem "protectedAsset" property

iOS9.2-: Judge MPMediaItem"assetURL"property is nil or not

Justin Kents' solution works great. I recommend using blocks though or else the UX will suffer if you deal with a bunch of songs:

-(void)checkDRMprotectionForItem:(MPMediaItem*)item OnCompletion:(void (^)(BOOL drmProtected))completionBlock
{
    dispatch_async(_drmCheckQueue, ^{
        BOOL drmStatus;
        NSURL* assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
        if (!assetURL) {
            drmStatus = YES;
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (completionBlock) {
                completionBlock(drmStatus);
            }
    });
    });
}

Now I'm building on swift 2 for ios 9, I found my code broken using hasProtectedContent or using nil url test. I've found the following code work:

    let playerItem = AVPlayerItem(URL: mpMediaItem.assetURL!)
    playableByAVPlayer = (playerItem.status == .ReadyToPlay) ? true : false

If the item is not playable by AV Player, then it's a DRM item and should be played by iPod Player (now called SystemMusicPlayer).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!