Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening iTunes Store to specific song

Ok, I have seen similar questions here but none are actually answering the problem for me.

I have a streaming audio app and the stream source returns to me the song title and artist name. I have an iTunes button in the app, and want to open the iTunes STORE (search) to that exact song, or at least close. I have tried the following:


NSString *baseString = @"itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?songTerm=";

NSString *str1 = [self.songTitle2 stringByReplacingOccurrencesOfString:@" " withString:@"+"];

NSString *str2 = [self.artist2 stringByReplacingOccurrencesOfString:@" " withString:@"+"];

NSString *str = [NSString stringWithFormat:@"%@%@&artistTerm=%@", baseString, str1, str2];

[[UIApplication sharedApplication] openURL: [NSURL URLWithString:str]];

This call does indeed switch me to the iTunes STORE as expected, but then it pops up an error "Cannot connect to iTunes Store". I am obviously on-line as the song is actively streaming, and I am in the store. The search box in iTunes app only shows the song name and nothing else.

Here is an example of a generated string: itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?artistTerm=Veruca+Salt&artistTerm=Volcano+Girls

I have tired taking the string it generates and pasting it into Safari, and it works OK on my Mac, opening to albums from the artist in the store. Why not on the phone?

Also, it seems to ignore both items, as it does not take me to the song by that artist. Does this require also knowing the album name (which I do not have at this time.)

Help would be appreciated. Thanks.

like image 606
MajorHavoc Avatar asked Jan 30 '13 07:01

MajorHavoc


1 Answers

Yes, I am answering my own question.

After much digging and a talk with one of the best programmers I know, we have a solution, so I thought I would share it here. This solution takes the song name and artist, actually does make a call to the Link Maker API, gets back an XML document, and extracts the necessary info to create a link to the iTunes Store, opening the store to the song in an album by that artist that contains the song.

In the interface of the view controller, add:

@property (strong, readonly, nonatomic) NSOperationQueue* operationQueue;
@property (nonatomic) BOOL searching;

In the implementation:

@synthesize operationQueue = _operationQueue;
@synthesize searching = _searching;

Here are the methods and code that will do this for you:

// start an operation Queue if not started
-(NSOperationQueue*)operationQueue
{
    if(_operationQueue == nil) {
        _operationQueue = [NSOperationQueue new];
    }
    return _operationQueue;
}
// change searching state, and modify button and wait indicator (if you wish)
- (void)setSearching:(BOOL)searching
{
// this changes the view of the search button to a wait indicator while the search is     perfomed
// In this case
    _searching = searching;
    dispatch_async(dispatch_get_main_queue(), ^{
        if(searching) {
            self.searchButton.enabled = NO;
            [self.searchButton setTitle:@"" forState:UIControlStateNormal];
            [self.activityIndicator startAnimating];
        } else {
            self.searchButton.enabled = YES;
            [self.searchButton setTitle:@"Search" forState:UIControlStateNormal];
            [self.activityIndicator stopAnimating];
        }
    });
}
// based on info from the iTunes affiliates docs
// http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
// this assume a search button to start the search. 
- (IBAction)searchButtonTapped:(id)sender {
    NSString* artistTerm = self.artistField.text;  //the artist text.
    NSString* songTerm = self.songField.text;      //the song text 
    // they both need to be non-zero for this to work right.
    if(artistTerm.length > 0 && songTerm.length > 0) {

        // this creates the base of the Link Maker url call.

        NSString* baseURLString = @"https://itunes.apple.com/search";
        NSString* searchTerm = [NSString stringWithFormat:@"%@ %@", artistTerm, songTerm];
        NSString* searchUrlString = [NSString stringWithFormat:@"%@?media=music&entity=song&term=%@&artistTerm=%@&songTerm=%@", baseURLString, searchTerm, artistTerm, songTerm];

        // must change spaces to +
        searchUrlString = [searchUrlString stringByReplacingOccurrencesOfString:@" " withString:@"+"];

        //make it a URL
        searchUrlString = [searchUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSURL* searchUrl = [NSURL URLWithString:searchUrlString];
        NSLog(@"searchUrl: %@", searchUrl);

        // start the Link Maker search
        NSURLRequest* request = [NSURLRequest requestWithURL:searchUrl];
        self.searching = YES;
        [NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error) {

            // we got an answer, now find the data.
            self.searching = NO;
            if(error != nil) {
                NSLog(@"Error: %@", error);
            } else {
                NSError* jsonError = nil;
                NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if(jsonError != nil) {
                    // do something with the error here
                    NSLog(@"JSON Error: %@", jsonError);
                } else {
                    NSArray* resultsArray = dict[@"results"];

                    // it is possible to get no results. Handle that here
                    if(resultsArray.count == 0) {
                        NSLog(@"No results returned.");
                    } else {

                        // extract the needed info to pass to the iTunes store search
                        NSDictionary* trackDict = resultsArray[0];
                        NSString* trackViewUrlString = trackDict[@"trackViewUrl"];
                        if(trackViewUrlString.length == 0) {
                            NSLog(@"No trackViewUrl");
                        } else {
                            NSURL* trackViewUrl = [NSURL URLWithString:trackViewUrlString];
                            NSLog(@"trackViewURL:%@", trackViewUrl);

                           // dispatch the call to switch to the iTunes store with the proper search url
                            dispatch_async(dispatch_get_main_queue(), ^{
                                [[UIApplication sharedApplication] openURL:trackViewUrl];
                            });
                        }
                    }
                }
            }
        }];
    }
}

The XML file that comes back has a LOT of other good info you could extract here as well, including three sizes of album art, album name, cost, etc, etc.

I hope this helps someone else out. This stumped me for quite some time, and I thank a good friend of mine for making this work.

like image 122
MajorHavoc Avatar answered Oct 02 '22 06:10

MajorHavoc