Need to see if your shared folder is taking up space on your dropbox 👨💻? Find out how to check here.
Forum Discussion
Bob S.15
9 years agoCollaborator | Level 9
migrating from API 1 to 2 - how do I know if I have OAuth 1 tokens?
I am finally getting around to updating my OLD apps from the original Dropbox IOS API to the new one. I'm looking at the migration guide, and the first thing it says is to check my OAuth tokens to se...
Greg-DB
Dropbox Community Moderator
9 years agoIt sounds maybe like the architecture settings for your app and the pods don't match, or that you don't have arm64 listed in your build architectures. You can configure these in your project's "Build Settings", under "Architectures".
Bob S.15
9 years agoCollaborator | Level 9
Okay thanks -- I looked at those and that stuff seems to match, but I have bigger problems for now.
Sorry for all the questions. I'm coming to this after several years of not touching this Dropbox code. I'm looking through my project for any reference to an OAuth token and not finding it. It looks like I set up the connection to Dropbox this way:
DBSession* dbSession =
[[[DBSession alloc]
initWithAppKey:@"xxxxxxxxx"
appSecret:@"xxxxxxxxx"
root:kDBRootAppFolder]
autorelease];
[DBSession setSharedSession:dbSession];
and then I use something called the 'restClient' to do all the interaction, like this:
restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
[restClient createFolder:path];
[restClient uploadFile:filename toPath:toPath fromPath:pngPath];
Does that look familiar? How would I go about moving to the new API from this?
- Greg-DB9 years ago
Dropbox Community Moderator
The SDK handles the access token retrieval and storage for you, so you wouldn't have had to deal with it manually before, but you'll need to extract them in order to hand them off to the new SDK.
As far as the client for the new SDK is concerned, I recommend working through the readme here, which shows how to configure the authorization flow, and get a client for making calls:
https://github.com/dropbox/dropbox-sdk-obj-c#configure-your-project
- Bob S.159 years agoCollaborator | Level 9
Hey Greg,
I don't really see anything in this Getting Started about tokens or extracting them? https://github.com/dropbox/dropbox-sdk-obj-c#get-started
I don't understand where these tokens come into it. It seems like if I just follow the authorization flow as described in "Getting Started", it would authorize the app?
EDIT: If you saw that earlier post about the 'image not found' error, I fixed that. I didn't have the framework as an embedded binary...
Thanks!
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
Hi Bob, yes, if you just follow the getting started guide you linked to, that will have you implement the app authorization flow, allowing users to link to and use your app. That will handle getting new tokens for you and storing them.
It's only if you were using an old SDK and want to automatically migrate the previously stored access tokens from that in your app would you need to put in the extra work to do so, e.g., using the technique from this old blog post.
- Bob S.159 years agoCollaborator | Level 9
Hey Greg,
I have a couple of questions about the regular authorization flow. If I don't have pre-existing tokens, I'm using the web form login to authorize the user. It put up a screen that says "<AppName> would like access to its own folder, Apps->AppName, inside your Dropbox, Learn More." and you can click Cancel or Allow.
If I click Allow, instead of returning to the app immediately, it shows a pop-up dialog that says "Open in "AppName"?" and you again have to press Cancel or Open. That seems wrong. Is it really required to do that second dialog or am I doing something wrong?
Also, once I have done this, how to I get it to remember that it is logged into the app? Currently I have to go through this authorization every time I run the app.
Thanks,
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
That "Open in" confirmation is part of iOS itself and was introduced by Apple somewhat recently (either iOS 9 or iOS 10 if I recall correctly) in order to let the user prevent unwanted redirects between apps. Consequently, that is expected, and we don't have control over it.
Also, the SDK should automatically store the authorization for you. Did you finish setting up the authorization flow as documented in the guide? Are you getting any errors? - Bob S.159 years agoCollaborator | Level 9
Hey Greg,
I have the authorization flow set up -- but the Getting Started guide only describes how to authorize the user, it doesn't say anything about handling when the authorization has already happened. By looking at the DBRoulette example, it looks like I should check [DropboxClientsManager authorizedClient], is that right? If that is not nil then the user is already authorized?
My old app used to authorize and then get the user's account info. How would I do that with the new SDK? I see this Account structure here:
https://dropbox.github.io/dropbox-sdk-obj-c/api-docs/latest/Classes/DBUSERSAccount.html
But it isn't clear how to use the SDK to obtain the information? Is there an example somewhere of how to obtain the account info?
Thanks,
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
Yes, that's right, you should use authorizedClient like that.
You can use the DBUSERSRoutes.getCurrentAccount method to get the account information.
That would look like this:
[[client.usersRoutes getCurrentAccount] response:^(DBUSERSFullAccount *account, DBNilObject *_, DBRequestError *error) { if (account) { NSLog(@"%@", account); } else if (error) { NSLog(@"%@", error); } }];(Note that DBError was renamed to DBRequestError in 2.0.6, so make sure you use the right one, depending on what version you're using.)
- Bob S.159 years agoCollaborator | Level 9
Okay, thanks.
Also I wanted to ask you about retrieving old tokens. Now that I know the user can just re-authorize, it's not that big a deal, but I was trying to get it to work anyway.
My old phone is logged into Dropbox using the old version of the app. Then I run the new version to see if I can convert the old tokens. The new version does not recognize that the user is logged in already, which is expected. Then I call this:
NSArray *credentials = [bigApp getTokensFromSyncAPI];
But [credentials count] always returns 0. Shouldn't it return the old tokens?
Thanks
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
That code is written for getting tokens from the Sync SDK, but you're using the Core SDK, so the values would be a little different.
I put this together for you as a basic concept of how this would work for going from the Core SDK to the API v2 Objective-C SDK:
- (NSArray * )getTokensFromCoreSDK { NSString *keychainPrefix = [[NSBundle mainBundle] bundleIdentifier]; NSString *keychainId = [NSString stringWithFormat:@"%@.dropbox.auth", keychainPrefix]; NSDictionary *keychainDict = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: keychainId, (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne, (__bridge id)kSecReturnAttributes: (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue}; CFDictionaryRef result = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)keychainDict, (CFTypeRef * )&result); NSDictionary *attrDict = (__bridge_transfer NSDictionary * )result; NSData *foundValue = [attrDict objectForKey:(__bridge id)kSecValueData]; NSMutableArray *credentials = [[NSMutableArray alloc] init]; if (status == noErr && foundValue) { NSDictionary *savedCreds = [NSKeyedUnarchiver unarchiveObjectWithData:foundValue]; NSArray *credsForApp = [savedCreds objectForKey:@"kDBDropboxUserCredentials"]; for (NSDictionary *credsForUser in credsForApp) { NSDictionary *token = @{ @"userId": [credsForUser objectForKey:@"kDBDropboxUserId"], @"token": [credsForUser objectForKey:@"kMPOAuthCredentialAccessToken"], @"tokenSecret": [credsForUser objectForKey:@"kMPOAuthCredentialAccessTokenSecret"] }; [credentials addObject:token]; } } return credentials; } - (void)getAndSaveOAuth2TokensFromRetrievedOAuth1Tokens:(NSArray * )oauth1Tokens { DBTransportClient *transportClient = [[DBTransportClient alloc] initWithAccessToken:nil selectUser:nil userAgent:nil delegateQueue:nil forceForegroundSession:nil appKey:APP_KEY appSecret:APP_SECRET]; DropboxClient *client = [[DropboxClient alloc] initWithTransportClient:transportClient]; for (NSDictionary *oauth1Token in oauth1Tokens) { [[client.authRoutes tokenFromOauth1:[oauth1Token objectForKey:@"token"] oauth1TokenSecret:[oauth1Token objectForKey:@"tokenSecret"]] response:^(DBAUTHTokenFromOAuth1Result *result, DBAUTHTokenFromOAuth1Error *routeError, DBRequestError *error) { if (result) { NSLog(@"OAuth 2 access token: %@\n", result.oauth2Token); DBAccessToken *accessToken = [[DBAccessToken alloc] initWithAccessToken:result.oauth2Token uid:[oauth1Token objectForKey:@"userId"]]; [[DBOAuthManager sharedOAuthManager] storeAccessToken:accessToken]; } else { NSLog(@"%@\n%@\n", routeError, error); } }]; } }...
NSArray *oauth1Tokens = [self getTokensFromCoreSDK]; [self getAndSaveOAuth2TokensFromRetrievedOAuth1Tokens: oauth1Tokens];
I haven't tested that extensively, so be sure to test it well in your app. I hope it helps though!
- Bob S.159 years agoCollaborator | Level 9
Hey Greg,
That's great, thanks! That code works, but I think I am missing one step. After I go through and store the new tokens, how do I get it to recognize that it is authorized? I am finding that [DropboxClientsManager authorizedClient] is returning nil after storing the tokens. If I quit the app and then run it again, THEN it recognizes the app as being authorized. But how do I get it to know it's authorized without having to restart the app?
Another question if you do not mind. I am making progress with the SDK and have been able to upload files. But I don't understand why some DBFILESRoutes functions list two arguments for the return response, but they seem to require three in practice. For example -createFolder:autorename says it returns a DBFILESFolderMetadata object and a DBFILESCreateFolderError object, but XCode gives me an error unless there is also a third DBRequestError object. Is this a documentation mistake or is the third argument assumed but not shown for some reason?
Thanks!
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
I believe you can get that active within the same session using DropboxClientsManager.reauthorizeClient. Let me know if that doesn't work for you though.
Yes, the third one, a DBRequestError, applies to all calls and covers higher level failures (network issues, invalid access tokens, etc.) so it's not documented on each call individually.
- Bob S.159 years agoCollaborator | Level 9
Hey Greg,
Yes that worked, thanks!
In the process of debugging this I went through all of my various simulators and devices, because I don't know how to remove the OAuth2 tokens once they are on there. I ran the old app to get the old tokens installed, then ran the new one to test the retrieval. Is there any way to remove the new tokens in order to re-test the transfer?
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
Yea, you can use DBOAuthManager.clearStoredAccessToken for specific tokens, or DBOAuthManager.clearStoredAccessTokens for all tokens.
- Bob S.159 years agoCollaborator | Level 9
Ok, thanks Greg.
Also, when I use DBFILESgetMetadata, is there any way to tell if the path is a file or a folder? In the old SDK there was an 'isDirectory' field of the metadata structure, but I don't see one for DBFILESMetadata. ?
Also, if it IS a folder, then how do you access the contents of the folder? With the old SDK I uses a loop like this:
for (DBMetadata *file in metadata.contents)
Thanks
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
You can use isKindOfClass to check the type:
https://github.com/dropbox/dropbox-sdk-obj-c/blob/8d4fcca08a6673af35cf6e116810b13e3e6507e9/README.md#response-handling-edge-cases - Bob S.159 years agoCollaborator | Level 9
OK thanks, and how would you access the contents of the folder, is that included in the metadata or do you have to issue another call to get that? Would I have to use listFolder?
- Greg-DB9 years ago
Dropbox Community Moderator
Yes, you should use listFolder (and listFolderContinue) to get the contents of any given folder. - Bob S.159 years agoCollaborator | Level 9
Hey Greg,
If getMetaData returns an error, how do you retrieve the error information from DBFILESGetMetadataError? It looks like it only contains a path and a tag, and I can't tell what the tag is. The docs say it represents the "union's current tag state", but it doesn't show any values. Is there some other way to get information about why it failed or what the error is ?
Thanks,
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
You can use the "is" methods to check which member of the error union a particular instance of the error is, then you can access the respective property for the specific error value, as shown here:
https://github.com/dropbox/dropbox-sdk-obj-c#route-specific-errors
The documentation details which methods/properties are available for any given type, e.g., for DBFILESGetMetadataError:
https://dropbox.github.io/dropbox-sdk-obj-c/api-docs/latest/Classes/DBFILESGetMetadataError.html - Bob S.159 years agoCollaborator | Level 9
Thanks for the reply. I get that I can use the 'is' commands to check the error, but in the case of the metadata, there is a path and a tag. The path is pretty self evident. But what is the tag? The docs don't seem to provide any details about what that is. I'm just wondering in the case of an error, how I would go about determining the cause or reason. The path I already know. And it doesn't look like the tag tells me anything. Does that make sense?
Thanks!
- Greg-DB9 years ago
Dropbox Community Moderator
The "tag" is the way the API describes which member of the union the object is. The SDK uses it to determine what the "is" methods return. So, you don't need to access tag directly, as long as you use the "is" methods.
To get the actual error information, use the respective field. For example, DBFILESGetMetadataError.path gives you a DBFILESLookupError, which itself has various "is" methods to tell you which error it was (and so on, for any further nested errors).
- Bob S.159 years agoCollaborator | Level 9
Oh, I see, the path contains the error information. I had assumed the path was just the file pathname.
Thanks!
- Bob S.159 years agoCollaborator | Level 9
Hey Greg,
With the old API, when I got a file's metadata, the returned DBMetadata structure included the filename, the path, the revision, the total bytes, and the last modified date. Isn't that stuff commonly considered the metadata? With the new API, getMetadata seems like it only returns the filename and path, is that correct? How do I access that other information?
Thanks
Bob
- Greg-DB9 years ago
Dropbox Community Moderator
This information is still available, but it depends on the object type. The name and path are available on all DBFILESMetadata objects:
https://dropbox.github.io/dropbox-sdk-obj-c/api-docs/latest/Classes/DBFILESMetadata.html
Modified time, size, rev, etc. are available on DBFILESFileMetadata instances:
https://dropbox.github.io/dropbox-sdk-obj-c/api-docs/latest/Classes/DBFILESFileMetadata.html
(DBFILESFileMetadata is a sub-type of DBFILESMetadata.)
You can see an example of how to check and cast these types here:
https://github.com/dropbox/dropbox-sdk-obj-c#response-handling-edge-cases - Bob S.159 years agoCollaborator | Level 9
OK, thanks, I got it now.
Also - is it okay to use the pathDisplay variable as a replacement for the old API's 'path' variable? The docs say pathDisplay is only for display purposes, as if it might be incorrect sometimes. But the other option is 'pathLower' , which is a lower-case version. So what do you use if you just want the exact pathname, like what you had in the old API?
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
The Dropbox Community team is active from Monday to Friday. We try to respond to you as soon as we can, usually within 2 hours.
If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X, Facebook or Instagram.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!