Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-24372] iOS: Expose all missing MediaItem properties, allow Apple Music playback in Ti.Media.AudioPlayer

GitHub Issuen/a
TypeNew Feature
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2017-04-06T13:49:28.000+0000
Affected Version/sn/a
Fix Version/sRelease 6.1.0
ComponentsiOS
Labelsn/a
Reporter Ricardo Ramirez
AssigneeHans Knöchel
Created2017-02-04T03:27:16.000+0000
Updated2017-04-12T12:10:47.000+0000

Description

Issue Description

The feature consists on use the Ti.Media.openMusicLibrary to pick a sound file or an object with the file and the path.

Comments

  1. Hans Knöchel 2017-02-04

    This is not how the iOS music picker works. We *can* expose the assetURL property to the Titanium API, but that looks for example like this:
       ipod-library://item/item.mp3?id=332491690319073515
       
    Simply, because Apple does not allow the developer to grab music files from the music library to send them somewhere else (piracy, privacy-settings, ...). So yes, we can expose it, but they rather want to use the meta-data to loookup the song on Spotify / Apple Music and link that to the app, like Shazam does for example. Or, if they want to play the music, they should use the [Ti.Media.MusicPlayer](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media.MusicPlayer) to playback songs in a self-defined queue. Please advice what they want to do. *EDIT*: Side-note, this are all properties we could expose from the native API (we already have lots of them but iOS 8+ added tons more):
       // Properties marked filterable can also be used to build MPMediaPropertyPredicates (see MPMediaQuery.h).
       
       MP_EXTERN NSString * const MPMediaItemPropertyPersistentID NS_AVAILABLE(10_12_2, 4_2);              // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID persistentID NS_AVAILABLE_IOS(5_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyMediaType;                                            // filterable
       @property (nonatomic, readonly) MPMediaType mediaType NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyTitle;                                                // filterable
       @property (nonatomic, readonly, nullable) NSString *title NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumTitle;                                           // filterable
       @property (nonatomic, readonly, nullable) NSString *albumTitle NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumPersistentID NS_AVAILABLE(10_12_2, 4_2);         // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID albumPersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyArtist;                                               // filterable
       @property (nonatomic, readonly, nullable) NSString *artist NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyArtistPersistentID NS_AVAILABLE(10_12_2, 4_2);        // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID artistPersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumArtist;                                          // filterable
       @property (nonatomic, readonly, nullable) NSString *albumArtist NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumArtistPersistentID NS_AVAILABLE(10_12_2, 4_2);   // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID albumArtistPersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyGenre;                                                // filterable
       @property (nonatomic, readonly, nullable) NSString *genre NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyGenrePersistentID NS_AVAILABLE(10_12_2, 4_2);         // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID genrePersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyComposer;                                             // filterable
       @property (nonatomic, readonly, nullable) NSString *composer NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyComposerPersistentID NS_AVAILABLE(10_12_2, 4_2);      // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID composerPersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyPlaybackDuration;
       @property (nonatomic, readonly) NSTimeInterval playbackDuration NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumTrackNumber;
       @property (nonatomic, readonly) NSUInteger albumTrackNumber NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAlbumTrackCount;
       @property (nonatomic, readonly) NSUInteger albumTrackCount NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyDiscNumber;
       @property (nonatomic, readonly) NSUInteger discNumber NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyDiscCount;
       @property (nonatomic, readonly) NSUInteger discCount NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyArtwork;
       @property (nonatomic, readonly, nullable) MPMediaItemArtwork *artwork NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString *const MPMediaItemPropertyIsExplicit NS_AVAILABLE(10_12_2, 7_0);
       @property (nonatomic, readonly, getter = isExplicitItem) BOOL explicitItem NS_AVAILABLE_IOS(10_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyLyrics;
       @property (nonatomic, readonly, nullable) NSString *lyrics NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyIsCompilation;                                       // filterable
       @property (nonatomic, readonly, getter = isCompilation) BOOL compilation NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyReleaseDate NS_AVAILABLE(10_12_2, 4_0);
       @property (nonatomic, readonly, nullable) NSDate *releaseDate NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyBeatsPerMinute NS_AVAILABLE(10_12_2, 4_0);
       @property (nonatomic, readonly) NSUInteger beatsPerMinute NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyComments NS_AVAILABLE(10_12_2, 4_0);
       @property (nonatomic, readonly, nullable) NSString *comments NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyAssetURL NS_AVAILABLE(10_12_2, 4_0);
       @property (nonatomic, readonly, nullable) NSURL *assetURL NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyIsCloudItem NS_AVAILABLE(10_12_2, 6_0);                // filterable
       @property (nonatomic, readonly, getter = isCloudItem) BOOL cloudItem NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyHasProtectedAsset NS_AVAILABLE(10_12_2, 9_2);          // filterable
       @property (nonatomic, readonly, getter = hasProtectedAsset) BOOL protectedAsset NS_AVAILABLE_IOS(9_2);
       
       MP_EXTERN NSString * const MPMediaItemPropertyPodcastTitle;                                          // filterable
       @property (nonatomic, readonly, nullable) NSString *podcastTitle NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyPodcastPersistentID NS_AVAILABLE(10_12_2, 4_2);        // filterable
       @property (nonatomic, readonly) MPMediaEntityPersistentID podcastPersistentID NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyPlayCount;                                             // filterable
       @property (nonatomic, readonly) NSUInteger playCount NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertySkipCount;
       @property (nonatomic, readonly) NSUInteger skipCount NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyRating;
       @property (nonatomic, readonly) NSUInteger rating NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyLastPlayedDate;
       @property (nonatomic, readonly, nullable) NSDate *lastPlayedDate NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyUserGrouping NS_AVAILABLE(10_12_2, 4_0);
       @property (nonatomic, readonly, nullable) NSString *userGrouping NS_AVAILABLE_IOS(8_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyBookmarkTime NS_AVAILABLE(10_12_2, 6_0);
       @property (nonatomic, readonly) NSTimeInterval bookmarkTime NS_AVAILABLE_IOS(7_0);
       
       MP_EXTERN NSString * const MPMediaItemPropertyDateAdded NS_AVAILABLE(10_12_2, 10_0);
       @property (nonatomic, readonly) NSDate *dateAdded NS_AVAILABLE_IOS(10_0);
       
       // Matches the id used by MPMusicPlayerController to enqueue store tracks  
       MP_EXTERN NSString * const MPMediaItemPropertyPlaybackStoreID NS_AVAILABLE_IOS(10_3);
       @property (nonatomic, readonly) NSString *playbackStoreID NS_AVAILABLE_IOS(10_3);
       
  2. Hans Knöchel 2017-02-04

    PR (exposing *all* missing properties to be future-safe): https://github.com/appcelerator/titanium_mobile/pull/8817 Note: Please still read the above comment. If they expect to receive an URL of a file that they can send, they won't succeed. This is - once again - restricted by Apple's privacy settings. Test-Case:
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       
       var btn = Ti.UI.createButton({
           title: 'Open Music Library'
       });
       
       btn.addEventListener('click', function() {
           Ti.Media.openMusicLibrary({
               error: function(e) {
                   Ti.API.error('Error opening the music library: Check if permissions granted and ensure to run on device!');
               },
               success: function(e) {
                   var item = e.items[0];
       
                   // Some of the media item properties. Check the docs for more!
                   Ti.API.info('Title: ' + item.title);
                   Ti.API.info('Artist: ' + item.artist);
                   Ti.API.info('Album: ' + item.albumTitle);
                   Ti.API.info('Has Protected Asset: ' + item.hasProtectedAsset);
                   
                   if (!item.hasProtectedAsset) {
                       Ti.API.info('Asset URL: ' + item.assetURL);
                   }
       
                   Ti.API.info('Is Explicit: ' + item.isExplicit);
                   Ti.API.info('Date Added: ' + item.dateAdded);
               }
           })
       });
       
       win.add(btn);
       win.open();
       
       
  3. Harry Bryant 2017-04-12

    Verified as fixed, tested with demo code provided in JIRA ticket, including additional exposed media item properties. iOS 10.2 & 9.3. Tested On: iPhone 7 10.2.1 Device iPhone 5S 9.3.5 Device Mac OS Sierra (10.12.2) Ti SDK: 6.1.0.v20170410104407 Appc Studio: 4.8.1.201701192045 Appc NPM: 4.2.9-1 App CLI: 6.1.0 Xcode 8.2.1 Node v4.6.0 *Closing ticket.*

JSON Source