We love Dropbox: free storage space, simple enough for our grandma to use and responsive customer service. Speaking of which, long live Brian S.!
If you are working on an AIR mobile app and want to integrate Dropbox, you may have noticed that there isn’t an official Dropbox Actionscript SDK. There is however an independent solution, kindly provided by grossopa, which wraps around OAuth and JSON and does most of the hard work talking to the Dropbox API for you: dropbox-as3.
Responding to changes in the Dropbox API
These happen, as the API evolves or has to be modified for… well, political reasons. Keeping up with the changes, while using a third party SDK isn’t always easy.
I’ll walk you through the bigger changes that have happened so far and what we’ve done to keep up with them.
In the beginning there were username and password
Initially, an app could link to a user’s Dropbox account by asking for username and password and using these to make a request to the Dropbox API.
Then came OAuth
Later Dropbox switched to OAuth authentication: instead of handling usernames and passwords itself, an app would switch to a browser, where the user would log in to Dropbox to authorize the link, then the browser would switch back to the app, telling it whether the linking was authorized.
Then Apple took umbridge…
A few weeks ago there was a wave of rejections of iOS apps from the App Store, which were using browser authentication. The story was all over the web, but the dialog on the Dropbox forum captured it best:
Apple rejecting applications which use Dropbox. The horror.
At DiaDraw we were gutted, but decided to release version 1.0 of IdeaDraw out without its Dropbox feature, while Dropbox and Apple were trying to agree a solution.
In the end the Dropbox iOS SDK was changed, so switching to an external browser is no longer required. The two ways of autorhizing your app to link with Dropbox are as follows.
If the user has the Dropbox app installed, it handles the authorization for you and shares credentials with your app – this is not new:
What is new is that if the user doesn’t have the Dropbox app installed, instead of switching to an external browser, the Dropbox log-in and authorization page is now shown in a view inside your app:
What happens if you use ActionScript?
For developers of native apps the change meant that they had to download the latest Dropbox iOS SDK and rebuild.
With ActionScript however we were faced with the need to somehow replicate the changes. Not massive fans of repeating work, we thought we’d have the best of both worlds:
- use the Dropbox iOS SDK for the autorization step;
- stick with dropbox-as3 for doing everything else.
In order to take advantage of the Dropbox iOS SDK (and the credential sharing, which in ActionScript would be trickier) we wrote a native extension that takes care of the authorization. It’s yours to use and modify.
The native extension – code and binaries
Can be downloaded here:
https://code.google.com/p/diadraw-air-dropbox-native-extension-example/
There is also an example app and detailed instructions on how to set it up and run it to demo the extension – check out the Wiki pages:
https://code.google.com/p/diadraw-air-dropbox-native-extension-example/wiki/ExampleApp
How to use the extension
0. Download the latest Dropbox iOS SDK
from
https://www.dropbox.com/developers/reference/sdk and copy DropboxSDK.framework into your iPhoneOSx.x.sdk Frameworks folder, typically in
[sourcecode language=”actionscript3″]
/Developer/Xcode.app/Contents/Developer/
Platforms/iPhoneOS.platform/Developer/SDKs/
iPhoneOS6.0.sdk/System/Library/Frameworks
[/sourcecode]
if you use iOS 6.0 SDK
or in
[sourcecode language=”actionscript3″]
/Developer/Xcode.app/Contents/Developer/
Platforms/iPhoneOS.platform/Developer/SDKs
/iPhoneOS5.1.sdk/System/Library/Frameworks
[/sourcecode]
if you use iOS 5.1 SDK.
1. Create an instance of NativeDropboxLogin
and make sure you listen for the event, which will tell you when your app has linked to Dropbox:
[sourcecode language=”actionscript3″]
private var m_loginExt : NativeDropboxLogin;
m_loginExt = new NativeDropboxLogin();
m_loginExt.addEventListener( "DROPBOX_EXT_LINKED", handleDropboxLinked );
[/sourcecode]
2. Call linkWithDropbox()
on that instance and pass it your app’s key, secret and how it will access Dropbox (“kDBRootDropbox” or “kDBRootAppFolder“):
[sourcecode language=”actionscript3″]
m_loginExt.linkWithDropbox( APP_KEY, APP_SECRET, "kDBRootDropbox" );
[/sourcecode]
3. Add CFBundleURLSchemes to your application descriptor file
(yourApp-app.xml) in the
<iPhone> section and make sure it has this format: db-YOUR-APP-DROPBOX-KEY
[sourcecode language=”xml”]
<![CDATA[
…
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>db-bsrweprjfs</string>
</array>
</dict>
</array>
]]>
…
[/sourcecode]
This URL scheme is used by the Dropbox app to invoke your application and let it know whether the user authorized linking or not.
4. Wait for the com.diadraw.extensions.dropbox.NativeDropboxLinkEvent event
Once you receive it, make a request for the access secret and access token, which you can then use to make requests for browsing, uploading, etc. file management on Dropbox.
This one is dispatched with or without additional information:
- if the app has already been linked previously, the event will come back with its userId, token and tokenSecret all null; in this case make a request for the access secret and access token, which you can then use to make requests for browsing, uploading, etc. file management on Dropbox.
- if the app has just been authorised to link with Dropbox, the event will contain the userId, token and tokenSecret, which you can use to start making requests.
[sourcecode language=”actionscript3″]
m_loginExt.addEventListener( NativeDropboxLinkEvent.DROPBOX_LINKED, handleDropboxLinked );
private function handleDropboxLinked( _event : NativeDropboxLinkEvent ) : void
{
if ( null != _event.token && null != _event.tokenSecret )
{
m_dropboxAPI.config.accessTokenKey = _event.token;
m_dropboxAPI.config.accessTokenSecret = _event.tokenSecret;
signalLoginComplete( _event.token, _event.tokenSecret );
}
else
{
getRequestToken();
}
}
[/sourcecode]
[Note: This is only relevant if you build with Adobe AIR 3.2 or lower] Orientation – beware
Since the extension potentially creates a native view, this can cause the rest of your app to spontaneously reorient itself in strange ways once the native view comes into play.
This has been taken care of with the UIViewController (Orientation) category in the native code.
If you are curious why and how this works, have a look at this post:
Native extensions for mobile AIR apps – getting round the orientation issue
Hi,
My app switches to the DropBox app, I can see my app name and even icon I added online, I grant access with the account I made the app with, the iPad switches back to my app but the event DROPBOX_EXT_LINKED never arrives. I got a desktop notification that the app folder had been made, so I guess everything worked. Any pointers? Thanks a mil!
Sander.
Hi Sander,
Thank you for spotting this!
There are two different cases, in which we need to know that we’re linked to Dropbox: when the user has just allowed it and when they have previously allowed linking with our app and the app is now just trying to establish connection.
The extension was only sending the DROPBOX_EXT_LINKED signal in the second case. In the case when the user had just allowed linking my example app was relying on working it out from the URL that was passed to it, when it was invoked.
I have now changed that so that it’s all handled by the extension and you should get the signal in either case.
I’ve also added a class for the event, NativeDropboxLinkEvent, so you listen for NativeDropboxLinkEvent.DROPBOX_LINKED, instead of for the literal string.
The two cases in which NativeDropboxLinkEvent.DROPBOX_LINKED is received are a bit different:
There is now an example of this in the test app that comes with the extension; I also updated the example in the post above and in the Google Code WiKi.
[sourcecode language=”actionscript3″]
m_loginExt.addEventListener( NativeDropboxLinkEvent.DROPBOX_LINKED, handleDropboxLinked );
private function handleDropboxLinked( _event : NativeDropboxLinkEvent ) : void
{
if ( null != _event.token && null != _event.tokenSecret )
{
m_dropboxAPI.config.accessTokenKey = _event.token;
m_dropboxAPI.config.accessTokenSecret = _event.tokenSecret;
signalLoginComplete( _event.token, _event.tokenSecret );
}
else
{
getRequestToken();
}
}
[/sourcecode]
Hope this helps. Let me know if you run into any more issues.
Radoslava
You’re pretty awesome! I’m gonna test this asap in my code and the example.
I’ve had my DropBox app approved by the DropBox team in the mean time, I thought the “developer status” was somehow messing things up. Comes in handy anyway, because I want to share my developer builds with several testers using TestFlight (native extension for air), and don’t want to be limited to 5 Dropbox Test users in the dev app.
I’ll keep you posted on my progress!
This update fixed my connection, but makes my app change orientation which I denied in app descriptor.
Your note said “This is only relevant if you build with Adobe AIR 3.2 or lower”, but it also happened with 3.3 and 3.4. I tried listening to StageOrientationEvent.ORIENTATION_CHANGING and StageOrientationEvent.ORIENTATION_CHANGE to try and preventDefault them, but neither are firing (perhaps because orientation was asked to be fixed in app descriptor). I was testing on iOS 5.1 and 6.0, using default iOS SDK (no -platformSDK flag in compiler arguments). Any thoughts? Is AIR 3.5 supposed to fix this, or is it a problem with the .ane? Thanks!
Hi Sander,
Turns out I can’t blame the AIR SDK this time (darn! :)), the ANE needed a little more work to be fully updated for iOS 6.0.
The way we had our extensions behave when it came to orientation worked with iOS 5, but got deprecated in iOS 6. There is a new blog post explaining the change for anyone out there making their own extensions: Making AIR native extensions: orientation on iOS 6.
I’ve updated the Dropbox Login ANE, as well as our e-mail extension ANE – see if that solves the problem for you and let me know if not.
Thanks for reporting this!
Radoslava
Any chance this get updated to support x64 bit requirements from apple?