Authenticating Dropbox in iOS - objective-c

I am adding Dropbox support to my iOS application. Using the official Dropbox API and the tutorials online here I have gotten to the point where Dropbox needs to be authenticated. The code below is what is given to Authenticate when a button is pressed:
//MainViewController.m
....
#implementation CryptoMainViewController
.....
#pragma mark - Dropbox
- (void)didPressLink {
if (![[DBSession sharedSession] isLinked]) {
[[DBSession sharedSession] link];
}
}
But no matter how I change the code, where I put it or what button I link it to, nothing will happen. Using breakpoints I've found that the method does in-fact get triggered. I've even put it in an IBAction, but this gives the same result. What am I doing wrong? How can I get my app to authenticate the end-user?
And, once authenticated, How can I save an NSString to the user's Dropbox?
If this is just totally wrong, then where can I go to find resources on how to do this properly?
The whole tutorial, all of the documentation, api, etc. is available here.

I had the same problem; the reason was that I hadn't set the shared Dropbox session, e.g.
DBSession* dbSession = [[[DBSession alloc] initWithAppKey: #"your_app_key"
appSecret: #"your_app_secret"
root: kDBRootAppFolder] autorelease];
[DBSession setSharedSession: dbSession];
Once that was called the link worked fine.

this answer may be late but im guessing that you already linked your app before and want to do so again. The only way you can have the process of linking taking place again is if you run the following code:
[[DBSession sharedSession] unlinkAll];
You can place it in your viewDidLoad. When you then call didPressLink: the app should open up dropbox app(if available), safari or an in app window asking for your permission to access your dropbox. If this does not happen then the problem is somewhere else. Hope this helps

Does your view implement the <DBLoginControllerDelegate> ?
If so, link Dropbox like so:
DBLoginController* controller = [[DBLoginController new] autorelease];
controller.delegate = self;
[controller presentFromController:self];

Related

iOS 9 Universal Links - no parameters recieved

Using the new iOS 9 feature - Universal links, from my understanding, is supposed top open my app whenever a specific domain is opened in browser (or other apps?). I have gone through the documentation and through this guide.
However, when the app opens I do not receive the parameter that is meant to help me open the correct page for the user to view....
I would share the code I'm using, but it's quite a big infrastructure and not really a couple of lines of code (server side JSON, plist rows and some IDs on the developer portal).
Anyone encountered it and could give me a hand here, please?
The Branch guide you linked to (full disclosure: I work with the Branch team) unfortunately doesn't cover a rather important step: what to do after your app opens. Which is exactly the issue you're encountering :). But the good news is you've already done the hard part with all the server and entitlement config.
What you need to complete the loop is a continueUserActivity handler in your AppDelegate.m file. This will pass you a webpageURL property containing the actual URL of the Universal Link that opened your app, which you can then parse and use for routing. It'll look something like this:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSString *myUrl = [userActivity.webpageURL absoluteString];
// parse URL string or access query params
}
return YES;
}
Also, when testing keep in mind that Universal Links unfortunately don't work everywhere yet:
P.S., gotta ask...since you found the Branch blog already, had you considered using the service to handle the link routing for you? It can definitely help simplify things!

Access contents of Watchkit extension's host's mainBundle

I'm writing a WatchKit extension and I'd like to read a file out of the host application's [NSBundle mainBundle]. I've tried [NSBundle bundleWithIdentifier:] but that just returns nil.
I have several potential workarounds, but nothing that would be as simple as "just read what you need from the host's mainBundle".
Is there a way of doing this?
The host app and your WatchKit extension can share files in only one of two ways, as far as I know:
Shared app group
Including a file in both targets
They run in separate processes and aren't accessible to each other outside of approved methods.
I ran into a similar problem like yours. The main host app has a particular pList that I needed to read, and I couldn't read from watch extension because they are isolated.
So in the watch I invoked the openParentApplication method
and in the main application my handler was something along the lines of
-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
NSString *request = [userInfo objectForKey:#"request"];
if ([request isEqualToString:ReadFile])
{
//read the file. and then i like to put it into a NSDictionary
NSDictionary *responseDictionary = //whatever
reply(responseDictionary);
}
else{ reply(nil); }
}
And then the contents were returned to me in the callback closure on the watch of the openParentApplication. Seems to work. Though your situation could be different in which case this method might not be viable.
From the Apple WatchKit programming guide:
To share preferences data between apps, create an NSUserDefaults object using the identifier of the shared group. The initWithSuiteName: method of NSUserDefaults creates an object that allows access to the shared user defaults data. Both processes can access this data and write changes to it.
Your main app can write a NSDictionary/NSArray to the shared prefs, and then the watch kit can pull it out, without starting the main app - however, the main app will have to be run at least once to update the shared prefs.

gtm-oauth2 crash on Mac OSX when authenticating with Instagram API

I'm building a small Instagram client for personal use on Mac OSX. I'm currently using gtm-oauth2 to obtain an oauth2 token from Instagram. I'm following the guide provided with the source to obtain this token. I've got it 90% working. The webView loads with the authentication details, and I can enter my account and the permissions screen comes up asking if I would like to grant my application access. The issue I'm running into is that after authenticating, regardless of whether I "Allow" or "Cancel", the application crashes with no stack trace or additional information. The only info I get regarding the exception is "Thread 1: EXC_BAD_ACCESS (code = 1, address=0x4c1)" and it appears that the thread is doing something to do with the WebCore::ResourceLoader, but it's a bunch of ASM so I've got no idea where this call is actually occurring. Perhaps I'm not calling the windowController properly? I've got my code included below.
- (void)signIntoInstagram {
NSURL *tokenURL =[NSURL URLWithString:kTOKENIURl];
// Set up the OAuth request
GTMOAuth2Authentication *auth = [GTMOAuth2Authentication
authenticationWithServiceProvider:#"Instagram"
tokenURL:tokenURL
redirectURI:kREDIRECTURI
clientID:KCLIENTID
clientSecret:KCLIENTSERCRET
];
// Specify the appropriate scope string, if any, according to the service's API documentation
auth.scope = #"basic";
NSURL *authURL = [NSURL URLWithString:KAUTHURL];
// Display the authentication view
GTMOAuth2WindowController *windowController;
windowController = [GTMOAuth2WindowController controllerWithAuthentication:auth
authorizationURL:authURL
keychainItemName:kKeychainItemName
resourceBundle:nil];
// optional: display some html briefly before the sign-in page loads
NSString *html = #"<html><body><div align=center>Loading sign-in page...</div></body></html>";
[windowController setInitialHTMLString:html];
[windowController signInSheetModalForWindow:_window
delegate:self
finishedSelector:#selector(windowController:finishedWithAuth:error:)];}
If I insert a breakpoint within the windowController:finishedWithAuth:error: method, the application is reaching it. However, it still crashes after I run through, which to me seems like some sort of asynchronous operation causing the error. Hopefully I'm just missing something simple here; I can't imagine there is a major flaw in Google's OAuth project.
I found this on a Google group after having the same problem https://groups.google.com/forum/#!msg/gtm-oauth/N6jlOpL9k5g/n4TdrTJyxzcJ . There is also an issue logged for it https://code.google.com/p/gtm-oauth/issues/detail?id=11
Basically I commented out line 331 of GTMOAuth2WindowController.m and it worked. You can also add your vote to the issue and maybe Google will fix it.

Stumped that [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] keeps returning nil

I have written a simple test application (Mac/Cocoa) to connect to the Key-Value store in iCloud. I seem to be falling at the first fence.
You can see the code for my simple app here and you'll see that I am not getting a URL back from "URLForUbiquityContainerIdentifier" call.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (!ubiq)
NSLog(#"No iCloud");
else
NSLog(#"Yes iCloud");
}
Screenshot of the app running with output:
In term of trying to see if I've everything setup correctly I looked at the setup of my App Id (Test app is called Radio) in the developer provisioning centre:
So that seemed to be ok. Then I re-created my provisioning profile (called Radio Dev 2) and checked that it was using the correct App Id:
Ok, so that also seemed to be ok. I then checked that entitlements was switched on and Key-Value container was activated:
So they are activated. I then took a look at the file itself, just to see if anything jumped out:
So I couldn't see anything jumping out at me in the entitlements file. Lastly, I confirmed that I was signing the build with the correct cert using the provisioning profile that I expected:
I was happy enough with that.
So I'm stumped. I've regenerated everything, etc, to no avail.
I'd really appreciate if anybody has any ideas. Have I missed anything?
Damien's comment on the question had the solution for me. For anyone using Xcode 4.5, you need to click the + below the Ubiquity Containers box. Until I did that, nothing worked.
I faced same problem. I noticed that in my device setting, I didnt logged in my icloud account. once done with adding my account iCloud. The issue was resolved.
In my case, I implement the Parts "Add Document Type" and "Add Exported UTI" of Section "Configuring your Project for iCloud". And, it will not keep return nil anymore.
http://www.raywenderlich.com/12816/icloud-and-uidocument-beyond-the-basics-part-3

Testing internet connection on iPad app using ios5

I have been searching through the forum regarding how to check whether there is internet or not in my ipad app. I just created a simple webview project with other view controllers and I need to display a UIAlert message when the internet is not available. In my case it is displaying the message when I run the app. When I run the app with internet and then deactivate the internet, it does not show the UIAlert message, that is if I switch between the views, it does not any more show the no internet connection.
I have followed this way of implementation in my project: (sorry my mistake this is the link I followed) http://mozymac.com/forums/f54/how-check-if-there-internet-connection-iphone-os-devices-595/ [This is the new edited question]
Apart from that I went through some of the previous questions in Stackoverflow forum like for ex: How to check for an active Internet connection on iOS or OSX?
But everybody has their own version. If any one has a much more updated method for ios5, xcode 4.2.1 of how to accomplish this then would be helpful for me.
Thanks
Is there a reason why you want to check for internet connection before actually trying to load a request in the UIWebView?
Best practice is to just start loading, and use your UIWebViewDelegate/NURLConnectionDelegate to inspect the NSError to see what is wrong. In case of network failure you will receive an error with a domain equal to NSURLErrorDomain. The error code will indicate what the problem is, see the NSError codes enum.
And only after the first error start your reachability to see when the internet connection becomes available again. Or easier, just let the user retry.
Using the Reachability code will actually cause some overhead. It takes time to check if the internet is available, which you could just have used to set up the actual connection as well.
Example
Since you are using a UIWebView you should implement the following delegate method to be notified of errors.
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
if (![[error domain] isEqualToString:NSURLErrorDomain]) {
// not a nsurl error, take other appropriate action
return;
}
NSInteger code = [error code];
// show appropriate error to user, based on code
}
In this delegate method you should do whatever is needed to achieve what you want. You could retry the request yourself, show a message to the user or start listening for reachability changes using the code from the Reachability example provided by Apple.
Apple has one, it's called Reachability. Here's the link to it.
http://developer.apple.com/library/ios/ipad/#samplecode/Reachability/Introduction/Intro.html
Best way to check internet connection is Reachibility application
link
Or else
+ (BOOL)isNetworkAvailable
{
CFNetDiagnosticRef diag;
diag = CFNetDiagnosticCreateWithURL (NULL, (CFURLRef)[NSURL URLWithString:#"www.apple.com"]);
CFNetDiagnosticStatus status;
status = CFNetDiagnosticCopyNetworkStatusPassively (diag, NULL);
CFRelease (diag);
if ( status == kCFNetDiagnosticConnectionUp )
{
//NSLog (#"Connection is up");
return YES;
} else {
NSLog (#"Connection is down");
return NO;
}
}