link to a book in iBook store from an iphone app - iphone

After looking around I could not get a straight answer to the following case: can I link to a book in the iBook store from my iphone app without integrating the in-app purchases API?
As far as I know, iBooks does charge you for placing the book, so my logic says that it should be possible since otherwise you would be charged twice.
Many thanks.

If your app is targeting iOS 6.0 you can use the new SKStoreProductViewController to allow users to purchase iTunes, App Store, and iBooks content directly from your app without having to leave it.
Here is how to present it from a UIViewController. You must add the StoreKit.framework to your application.
ViewController.h
#import <StoreKit/StoreKit.h>
#interface UIViewController : UIViewController <SKStoreProductViewControllerDelegate>
#end
ViewController.m
-(void)showProductPageForProductID:(NSInteger)productID {
SKStoreProductViewController *sv = [[SKStoreProductViewController alloc] init];
sv.delegate = self;
NSDictionary *product = #{ SKStoreProductParameterITunesItemIdentifier: #(productID)};
[sv loadProductWithParameters:product completionBlock:^(BOOL result, NSError *error) {
if(result)
[self presentModalViewController:sv animated:YES];
else {
//product not found, handle appropriately
}
}];
}
-(void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[viewController dismissModalViewControllerAnimated:YES];
}
If your targeting devices below iOS 6.0 you can just use this:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://itunes.apple.com/us/book/the-casual-vacancy/id518781282?mt=11"]];
Just replace that URL string with your link, and it will leave your app and enter the iBooks app displaying that product.
If you want to target both iOS 6.0 and lower, you can just check if they have the new SKStoreProductViewController by using the following conditional
if([SKStoreProductViewController class]) {
//show the SKStoreProductViewController
}
else {
//use UIApplication's openURL:
}
In order to get the Apple product ID for a product, you can just check the URL to the product for example:
http://itunes.apple.com/us/book/the-casual-vacancy/id518781282?mt=11
The product ID is 518781282. It comes after the id portion in the URL. Don't include the ? or anything after it.

Related

ITunes review URL and iOS 7 (ask user to rate our app) AppStore show a blank page

Does anybody knows if the technique used to ask the user to rate our app and open for him the App Store directly on the rating page is still working on iOS 7 ?
I used to open this url from my app :
itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=353372460&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software
But it looks like it's not working anymore (AppStore show a blank page). I have also tried this url wihout luck:
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?pageNumber=0&sortOrdering=1&type=Purple+Software&mt=8&id=353372460
Starting with iOS7 the URL has changed and cannot direct for the review page but only to the app
itms-apps://itunes.apple.com/app/idAPP_ID
Where APP_ID need to be replaced with your Application ID. Based on the App ID from the question it would be the following
itms-apps://itunes.apple.com/app/id353372460
Notice the id in front of the number ... that string is is id353372460, not just 353372460
For anything pre iOS7 the 'old' URL needs to be used, only those could get you straight to the review page. You should also take note that these calls will only work on devices. Running them in the simulator will do nothing since the simulator does not have the App Store app installed.
Have a look at for instance Appirater for an implementation. https://github.com/arashpayan/appirater
Can't help you with phonegap specifics (never used it). But it basically comes down to checking the iOS version your user is running and then either use the old URL or then new iOS7 URL.
The following URL works perfectly on iOS 7.1:
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=xxxxxxxx&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8
where the xxxxxxxx is your app ID.
UPDATE. Works on iOS 9.3.4 and iOS 10 GM (by Jeet)
This works on my end (Xcode 5 - iOS 7 - Device!):
itms-apps://itunes.apple.com/app/idYOUR_APP_ID
For versions lower than iOS 7 use the old one:
itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=YOUR_APP_ID
One-Line-of-Code Simple Alternative: ** Also See Simulator Comments Below **
http://itunes.apple.com/app/idAPP_ID
EDIT: Now that iOS 7.1 allows direct-link to the Reviews tab in the App Store, it's worth investing the extra lines of code to get there directly: see other answers for the rest.
here we are using http: instead of itms-apps:, let iOS do the rest of the work
I get the same results testing on iOS 6.1 & 7 devices (iPad/iPhone/iPod touch 4)
Specifically, this shortcut, for iOS 6 takes the user to the Details tab and not the Reviews tab.
The Purple+Software link gets the user all the way to the Reviews tab in iOS 6, which is obviously preferred if you know how to check the OS.
Important note: This will cause error in the simulator for iOS 5.1, 6.1 and 7.Cannot Open Page Safari can not open the page because the address is invalid (we know it is a valid URL outside the simulator, on any browser)
Just to be clear: On iOS 7: http:// provides the same experience as itms-apps: with no noticeable delay. * keep in mind that the simulator behavior noted above. This is not entire dissimilar from trying to access the camera via a simulator: the simulator is not the place to test it. *
It's not clear which versions of iOS this is supported by, but as part of iOS 10.3 there's a new query parameter that can be added to the URL: action=write-review. I have tested this on iOS 10.2 and 9.3.5 and it works. However, it does not work on iOS 7.1.2, so support was added between iOS 8.0 and 9.3.5. Further investigation is required!
Example: https://itunes.apple.com/app/id929726748?action=write-review&mt=8
This will open the "Write a Review" dialogue, rather than just showing the review tab.
Opening review page directly from app is possible in iOS7.
Please use the following url...
itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=YOUR_APP_ID
This will definitely works.. :)
+ (NSString *)getReviewUrlByAppId:(int)appId
{
NSString *templateReviewURL = #"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID";
NSString *templateReviewURLiOS7 = #"itms-apps://itunes.apple.com/app/idAPP_ID";
NSString *templateReviewURLiOS8 = #"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software";
//ios7 before
NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:#"APP_ID" withString:[NSString stringWithFormat:#"%d", appId]];
// iOS 7 needs a different templateReviewURL #see https://github.com/arashpayan/appirater/issues/131
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 && [[[UIDevice currentDevice] systemVersion] floatValue] < 7.1)
{
reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:#"APP_ID" withString:[NSString stringWithFormat:#"%d", appId]];
}
// iOS 8 needs a different templateReviewURL also #see https://github.com/arashpayan/appirater/issues/182
else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
reviewURL = [templateReviewURLiOS8 stringByReplacingOccurrencesOfString:#"APP_ID" withString:[NSString stringWithFormat:#"%d", appId]];
}
return reviewURL;
}
The review link has once again broken in iOS9. In doing some experimenting, I figured out that Apple reverted it back to how it was before iOS7. So you have to do:
itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=247423477&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software
Where 247423477 is your 9 digit app ID (the main difference is you have to append &onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software after the app ID).
All the answers above have now been deprecated (iOS 7, but may work) thus, I provide the new way Apple recommends to provide links to the Apps.
The link for your App is the one from iTunes (use Copy Link), this one is recommended for use in code:
Swift 3.0
let path = URL(string: "https://itunes.apple.com/us/app/calcfast/id876781417?mt=8")
UIApplication.shared.open(path!)
Or better -- treat the optional correctly and handle the possibility of not being able to reach the link:
if let path = URL(string: "https://itunes.apple.com/us/app/calcfast/id876781417?mt=8") {
UIApplication.shared.open(path) {
(didOpen:Bool) in
if !didOpen {
print("Error opening:\(path.absoluteString)")
}
}
}
Objective-C
#define APP_URL_STRING #"https://itunes.apple.com/us/app/calcfast/id876781417?mt=8"
then you can call APP_URL_STRING in your code:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: APP_URL_STRING] options:#{} completionHandler:nil];
Note, that this is the recommended way now by Apple, as the previous method of processing redirect links has been deprecated and are not supported.
The link for all your Apps, if you have more than one:
#define MYCOMPANY_URL_PATH #"http://appstore.com/mycompany"
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: MYCOMPANY_URL_PATH] options:#{} completionHandler:nil];
The App link above is recommended for use in code or links that are not seen directly by the user. If you want to provide link that may be seen and remembered by the user then use the following:
http://appstore.com/calcfast
Using this URL was the perfect solution for me. It takes the user directly to the Write a Review section. Credits to #Joseph Duffy.
For a sample code try this :
Swift 3, Xcode 8.2.1 :
let openAppStoreForRating = "itms-apps://itunes.apple.com/gb/app/id1136613532?action=write-review&mt=8"
if UIApplication.shared.canOpenURL(URL(string: openAppStoreForRating)!) {
UIApplication.shared.openURL(URL(string: openAppStoreForRating)!)
} else {
showAlert(title: "Cannot open AppStore",message: "Please select our app from the AppStore and write a review for us. Thanks!!")
}
Here showAlert is a custom function for an UIAlertController.
I have this to get the Product ID automatically and generate App Store Review and Product page links.
- (void) getAppStoreLinks {
productID = [[NSUserDefaults standardUserDefaults] objectForKey:#"productID"]; //NSNumber instance variable
appStoreReviewLink = [[NSUserDefaults standardUserDefaults] objectForKey:#"appStoreReviewLink"]; //NSString instance variable
appStoreLink = [[NSUserDefaults standardUserDefaults] objectForKey:#"appStoreLink"]; //NSString instance variable
if (!productID || !appStoreReviewLink || !appStoreLink) {
NSString *iTunesServiceURL = [NSString stringWithFormat:#"https://itunes.apple.com/lookup?bundleId=%#", [NSBundle mainBundle].bundleIdentifier];
NSURLSession *sharedSes = [NSURLSession sharedSession];
[[sharedSes dataTaskWithURL:[NSURL URLWithString:iTunesServiceURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
if (data && statusCode == 200) {
id json = [[NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)0 error:nil][#"results"] lastObject];
//productID should be NSNumber but integerValue also work with NSString
productID = json[#"trackId"];
if (productID) {
appStoreReviewLink = [NSString stringWithFormat:#"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=%d&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8",productID.integerValue];
appStoreLink = [NSString stringWithFormat:#"itms-apps://itunes.apple.com/app/id%d",productID.integerValue];
[[NSUserDefaults standardUserDefaults] setObject:productID forKey:#"productID"];
[[NSUserDefaults standardUserDefaults] setObject:appStoreReviewLink forKey:#"appStoreReviewLink"];
[[NSUserDefaults standardUserDefaults] setObject:appStoreLink forKey:#"appStoreLink"];
}
} else if (statusCode >= 400) {
NSLog(#"Error:%#",error.description);
}
}
] resume];
}
}
Open app's Review Page
- (IBAction) rateButton: (id)sender {
NSString *appStoreReviewLink = appStoreReviewLink;
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appStoreReviewLink]];
}
Open app's App Store page
- (IBAction) openAppPageButton: (id)sender {
NSString *appStoreLink = appStoreLink;
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: appStoreLink]];
}
It is said that this bug will be fixed on iOS7.1. Read here on the corona forum, and here on the iPhoneDevSDK.

iOS Facebook API don't bring up the iPhone settings like Tweeter

I'm using DEFacebookComposeViewController for post a message in Facebook. When using iOS5 the user is redirected to the facebook page for login and then go back to the app, that works nice. But, in iOS6 the Service API show a UIAlertView that show the options "Settings" or "Cancel"
The problem is that bot buttons have the same effect. Both cancel the dialog (it's also happend in the 'FacebookSample' here).
In the other hand, the Tweeter framework woks fine in both iOS 5 and 6. The alerts appears if there is no tweeter account configured and the "Settings" button brings you to the "Add Account" screen.
All ideas are welcome.
Thanks
PD: all test where in the simulator.
Edit:
This is the code that I'm using:
DEFacebookComposeViewController *facebookComposer = [[DEFacebookComposeViewController alloc] init];
[facebookComposer setInitialText:#"Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test"];
__block id weakSelf = self;
[facebookComposer setCompletionHandler:^(DEFacebookComposeViewControllerResult result) {
[weakSelf dismissModalViewControllerAnimated:YES];
}];
[self presentModalViewController:facebookComposer animated:YES];
[facebookComposer release];
And this is the important part in the DEFacebookComposeViewController class;
- (id)init
{
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6) {
self = [(DEFacebookComposeViewController*)[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook] retain];
return self;
}
self = [super init];
if (self) {
[self facebookComposeViewControllerInit];
}
return self;
}
There. If the iOS version is 6 the init method return [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook] wich is the vanilla iOS6 way of interact with facebook.
How about using Social framework that is officially provided by Apple on iOS6, especially on iOS6 ?
Ex:
SLComposeViewController
 *viewController
= [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[self presentViewController:viewController animated:YES completion:nil];

What will happen to users running a lower version of IOS if new code is called?

I am fairly new to iOS Development and I've always wondered if a user running my application on iOS 4 were to try and run this code:
//POST TWEET//
- (void)showTweetSheet
{
TWTweetComposeViewController *tweetSheet =
[[TWTweetComposeViewController alloc] init];
tweetSheet.completionHandler = ^(TWTweetComposeViewControllerResult result) {
switch(result) {
case TWTweetComposeViewControllerResultCancelled:
break;
case TWTweetComposeViewControllerResultDone:
break;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"Tweet Sheet has been dismissed.");
}];
});
};
[tweetSheet setInitialText:#"Check out this cool picture I found on #Pickr_"];
// Add an URL to the Tweet. You can add multiple URLs.
if (![tweetSheet addURL:[NSURL URLWithString:ImageHost]]){
NSLog(#"Unable to add the URL!");
}
[self presentViewController:tweetSheet animated:YES completion:^{
NSLog(#"Tweet sheet has been presented.");
}];
}
What would happen? Would the application just terminate with an error or will the code just not run? And how do I properly implement features that are OS specific? Would I just use something like this:
NSString *DeviceVersion = [[UIDevice currentDevice] systemVersion];
int DeviceVersionInt = [DeviceVersion intValue];
if (DeviceVersionInt > 5)
{
//do something.
}
else
{
//don't do a thing.
}
It will crash on iOS 4 if you write iOS5 features without checking if they are available or not. Try to implement Twitter like this
Class twClass = NSClassFromString(#"TWTweetComposeViewController");
if (!twClass) // Framework not available, older iOS
{
//use iOS4 SDK to implement Twitter framework
}
else {
//use Apple provided default Twitter framework
}
Make sure you have added Twitter Framework with weak link.
Id imagine that it would work the same as with any other api. If you link against a function which is not in a previous version, the program will crash on an attempt to call the function. Therefore, version switches are used, as you demonstrated, to avoid crashes.
The app would crash. If you want to implement features based on iOS, you can use a variety of methods. See this question.

How to access Twitter Account Followers into iphone using iOS5? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Get twitter Follower in IOS 5
How to access Twitter Account Followers into iphone using iOS5?
I am new to iOS5 , can u please suggest with some code or links.
Thanks in Advance
Bhaskar
In IOS5 twitter is intregated.... then No Use Extra frameWork...
try this code
- (void)OnTwitter {
Class TWTweetComposeViewControllerClass = NSClassFromString(#"TWTweetComposeViewController");
if (TWTweetComposeViewControllerClass != nil) {
if([TWTweetComposeViewControllerClass respondsToSelector:#selector(canSendTweet)]) {
UIViewController *twitterViewController = [[TWTweetComposeViewControllerClass alloc] init];
[twitterViewController performSelector:#selector(setInitialText:)
withObject:twitterText];
[twitterViewController performSelector:#selector(addURL:)
withObject:[NSURL URLWithString:url]];
[twitterViewController performSelector:#selector(addImage:)
withObject:urImage];
[self presentModalViewController:twitterViewController animated:YES];
[twitterViewController release];
}
else {
// Use ShareKit for previous versions of iOS
}
}
import the farmeWork in your Class
#import <Twitter/Twitter.h>
#import <Accounts/Accounts.h>
You can use this link to find how to access twitter accounts
Then you can easily use the API to find the followers

How to check if UIDocumentInteractionController will fail to open document due to missing external application on iPad?

I am using UIDocumentInteractionController for showing popover menu "Open In..." so that user can open a document in other application.
Method presentOpenInMenuFromBarButtonItem:animated: returns NO in case there is no application able to open given document (menu will not show). But it is too late for me to wait until getting so far. I would like to disable the button initiating that opening if it is not possible instead of raising expectations of an user and then say "sorry, it is not possible to open it".
Is it possible to query system to see if there is at least one application registered for particular document type? I have checked canPreviewItem: in QLPreviewController, but it seems it doesn't support the same document types which UIDocumentInteractionController can handle.
[EDIT] Not working for iOS 6.0 (see comment)
It seems that dismissMenuAnimated (with no animation at all) is the key:
-(BOOL)canOpenDocumentWithURL:(NSURL*)url inView:(UIView*)view {
BOOL canOpen = NO;
UIDocumentInteractionController* docController = [UIDocumentInteractionController
interactionControllerWithURL:url];
if (docController)
{
docController.delegate = self;
canOpen = [docController presentOpenInMenuFromRect:CGRectZero
inView:self.view animated:NO];
[docController dismissMenuAnimated:NO];
}
return canOpen;
}
It will return YES if at least one application is able to open the file pointed by url.
At least it's working in my case (KMZ files), testing with/without Dropbox app on iPhone iOS 4.3.
Actually, it seems to work even if url is not pointing to an actual file (i.e. #"test.kmz"), but I wouldn't rely on it for all file types.
I came up with a less hacky way of doing things, but there is a limitation that you can only detect whether there's a compatible app after the user has selected to open in an app. This will enable you to provide the same user experience as the Dropbox app.
All you need to do is set up the UIDocumentInteractionControllerDelegate and create a boolean flag property that holds whether or not the menu was presented.
In the interface:
/**
The document interaction controller used to present the 'Open with' dialogue.
*/
#property (nonatomic,strong) UIDocumentInteractionController *documentInteractionController;
/**
Boolen that holds whether or not there are apps installed that can open the URL.
*/
#property (nonatomic) BOOL hasCompatibleApps;
In the implementation:
- (void)shareFileAtURL:(NSURL*)fileURL
{
[self setDocumentInteractionController:[UIDocumentInteractionController interactionControllerWithURL:fileURL]];
[[self documentInteractionController] setDelegate:self];
[self setHasCompatibleApps:NO];
[[self documentInteractionController] presentOpenInMenuFromRect:[self popoverRect] inView:[self popoverView] animated:YES];
if (![self hasCompatibleApps])
{
// Show an error message to the user.
}
}
#pragma mark - UIDocumentInteractionControllerDelegate methods
- (void)documentInteractionControllerWillPresentOpenInMenu:(UIDocumentInteractionController *)controller
{
[self setHasCompatibleApps:YES];
}
I hope that helps some people.
This works for me:
self.docController = [UIDocumentInteractionController interactionControllerWithURL:url];
UIView *v = [[UIView alloc] init];
BOOL isAnAppAvalaible = [self.docController presentOpenInMenuFromRect:CGRectZero inView:v animated:NO];
NSURL *url = [NSURL URLWithString:#"path_to_the_file"];
UIDocumentInteractionController *controller =
[UIDocumentInteractionController interactionControllerWithURL:url];
BOOL openResult = [controller presentPreviewAnimated:NO];
If you use presentPreviewAnimated: for showing files you can use openResult to detect if it was opened successfully.
-[UIApplication canOpenURL:] should do the job.