I've been looking at this tutorial for information on how to locate songs in a user's music library on their iPhone. Everything is working as it's supposed to, except that songs that are purchased but not on the user's phone do not play.
Does anyone know a way to fix this, or know how to test to see if the song is purchased vs installed and then alert the user?
Below is the code I'm using from the tutorial that selects and plays the songs:
/*
* This method is called when the user presses button. It displays a media picker
* screen to the user configured to show only audio files.
*/
- (IBAction)pickSong:(id)sender
{
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
[picker setDelegate:self];
[picker setAllowsPickingMultipleItems: NO];
[self presentViewController:picker animated:YES completion:NULL];
}
#pragma mark - Media Picker Delegate
/*
* This method is called when the user chooses something from the media picker screen. It dismisses the media picker screen
* and plays the selected song.
*/
- (void)mediaPicker:(MPMediaPickerController *) mediaPicker didPickMediaItems:(MPMediaItemCollection *) collection {
// remove the media picker screen
[self dismissViewControllerAnimated:YES completion:NULL];
// grab the first selection (media picker is capable of returning more than one selected item,
// but this app only deals with one song at a time)
MPMediaItem *item = [[collection items] objectAtIndex:0];
// display title of song in a navigation bar
//NSString *title = [item valueForProperty:MPMediaItemPropertyTitle];
//[_navBar.topItem setTitle:title];
// get a URL reference to the selected item
NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
// pass the URL to playURL:, defined earlier in this file
[self playURL:url];
}
Related
I am developing a small music application in which first view comprises of all the List of songs in Tableview and when user taps on any one row (song) it takes them to Second view & Plays the song their(comprising of play/Pause Buttons). Now I go back in First View from Second View using back button to select another song. And their is one button in First View for just switching views(i.e it takes to current playing song)but it plays that same song from start but not from its currentplaying . Its similar to now Playing button in Stock Music app in iOS.
Im using storyboards & Segues
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
temp = indexPath.row;
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[self performSegueWithIdentifier:#"Player" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Player"])
{
MPMediaItem *item = [itemCollections objectAtIndex:temp];
NSString *trackInfo = [[NSString alloc] initWithFormat:#"%#- %#",[item valueForProperty:MPMediaItemPropertyTitle],[item valueForProperty:MPMediaItemPropertyArtist]];
MPMediaItemArtwork *artwork = [item valueForProperty:MPMediaItemPropertyArtwork];
NSURL *tempURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
playerController = [segue destinationViewController];
playerController.fileUrl1 = tempURL;
playerController.globalVar = [NSNumber numberWithInteger:temp];
playerController.labelTitleString = trackInfo;
playerController.img = [artwork imageWithSize:CGSizeMake(100, 100)];
}
}
You could go about this in many ways -- I would suggest implementing a singleton to handle the media playback. Rather than constantly retaining that view, this singleton manager (part of your model) should provide any controllers with the needed information about the current song, album, author, etc.
Ex. In your TableViewController:
- (void)viewDidLoad
{
[self setSong:[[PlaybackManager sharedInstance] currentSong]];
if (self.song) {
//Add navigation item
}
}
I've got two strange diverging behaviours between iOS 6 and 7.
I want to present the MPMediaPicker to the end user, allow them to select 1 song, and start playing that back to them.
So, I show them the MPMediaPicker (/not/ multi, and /not/ cloud, if supported).
Two problems:
In iOS6, the first screen in MPMediaPicker shows the songs. In iOS7,
it's the (empty) playlists. How can I force the MPMediaPicker to
show songs as the default first screen? Is this just another example of Apple "knowing best"?
In iOS7 I get a red (+) symbol next to the media items in the list. What
causes that? I haven't been able to turn up any references for that
in google. What is the (+) symbol? It doesn't seem to highlight separately from the line in the table. The native media picker doesn't display this.
Thanks!
-Ken
Our MPMediaPicker code:
- (void)showSongPicker {
// TODO check if iOS 6
MPMediaPickerController* songPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
songPicker.delegate = self;
songPicker.allowsPickingMultipleItems = NO;
songPicker.showsCloudItems = NO;
[self presentViewController:songPicker animated:YES completion:nil];
[self presentModalViewController:songPicker animated:YES];
}
#pragma mark MPMediaPickerControllerDelegate
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
MPMediaItem* item = [mediaItemCollection.items objectAtIndex:0];
[self playMediaItem:item];
[self mediaPickerDidCancel:mediaPicker];
}
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
[self dismissViewControllerAnimated:YES completion:nil];
}
Oh! I do apologise. I'd forgotten to answer this.
Since I didn't get an answer from anyone else (until just now, thanks, lap.felix), I filed it as a technical question with Apple.
Their answer?
There's no programmatic way to affect the behaviour of the picker. If you need to change the behaviour this "drastically", you have to roll your own media picker.
So...yeah...thanks, Apple.
-Ken
The + doesn't mean anything other than "Add this item to the picker selection"
I'm a new developer and I'm getting to grips with audio in iOS.
This will be tricky to explain, but I'll give it a go. I'm using a media picker so that the user can select a song from their library. I don't want there to be a queue or for it to play immediately. Instead, I want it to appear in a tableview and when the user selects that song in the table view, it will play that when, in another view, a button is pressed.
So basically, I want the user to be able to select a song from their library and it is added to list. They can then selected a song from that list and It will play that when a button is pressed.
If it helps, this is the code I'm using for the media picker and to play audio (and they're not actually connected to each other):
Media Picker:
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
[mediaPicker setDelegate:self];
[mediaPicker setAllowsPickingMultipleItems:NO];
mediaPicker.prompt = NSLocalizedString(#"text1", "text2");
[self presentViewController:mediaPicker animated:YES completion:nil];
Playing Audio:
if (self.panicButtonPressed == NO) {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"Alarm 1"
ofType:#"mp3"]];
alarmSound = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:nil];
[alarmSound play];
self.panicButtonPressed = YES;
}
Any help would be greatly appreciated.
Once you get the file URL you can use it to access the files metadata (title,artist,etc.). You can then populate your table with this data and the URL.
I use standart image picker to make some camera photo.
When user makes photo image picker shows him the Preview screen with 2 buttons "Retake" and "Use".
How to detect that Preview screen is active now or "Retake" button pressed? Is it possible ? Are the useful properties or events? Something like when image source is library the is property - allows editing, which shows similar screen .
UIImagePickerController * imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
A bit after the fact, but maybe someone is still seeking this answer like I was. If you want continue using the native camera controls, you can check the subviews of the ImagePickerController to determine if the post-record view is showing.
BOOL videoTaken = NO;
for (UIView *aView in self.imagePickerController.view.subviews[0].subviews[0].subviews[0].subviews)
{
if ([aView isKindOfClass:NSClassFromString(#"PLTileContainerView")])
{
videoTaken = YES;
break;
}
}
The "PLTileContainerView" is the subview that contains the editing slider that lets you view your video frame by frame, so if it's present, that means your video has already recorded.
For use:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:NO];
NSString *type = [info objectForKey:#"UIImagePickerControllerMediaType"];
if ([type isEqualToString:#"public.movie"]) {
} else {
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
}
For Cancel you don't have a way of detecting it (other than subclassing UIImagePickerController, which may be prohibited, or other way that I'm not aware), but for sure the second cancel is detectable :
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated:YES];
}
I want to know when a user selects a song using media picker, what playlist they picked the song from. For some reason, the playlist doesn't seem to exist.
Basically when a user goes to a playlist in media picker let's call it "gym songs" and they select a song, mediaPicker:didPickMediaItems: function returns the song details but doesn't say which playlist the user selected the sone from.
So what I want to do is play that song and continue playing the other songs in that playlist. But without the playlist info, it starts playing that song and goes on playing the rest of the songs in "all songs" list.
This is my code:
(void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection
{
MPMediaItem *selectedSong = [[mediaItemCollection items] objectAtIndex:0];
MPMediaQuery *songQuery = [MPMediaQuery songsQuery];
[musicPlayer setQueueWithQuery:songQuery];
for (MPMediaItem *oneSong in [songQuery items]) {
if ([selectedSong isEqual:oneSong]) {
musicPlayer.nowPlayingItem = oneSong;
[musicPlayer play];
// Exit the loop
break;
}
}
[self dismissModalViewControllerAnimated: YES]; }
This data is not made available. Your only option is to do all this yourself in code. Put up a tableview and populate it with all the playlists in the library. When the user chooses a playlist put up another tableview with all the tracks in that playlist and allow the user to choose one.