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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With