Facebook Module Changes in Titanium Mobile 1.6.0

information superhighway

(Our Stephen Tramer contributed the portion of this article that concerns Facebook authentication in iOS.)

Titanium Mobile 1.6.0 (currently in its release-candidate stage) contains an upgraded Facebook module which uses new authentication features on both Android and iOS as well as a new set of methods to retrieve and submit data. Our new API documentation won’t get generated and put up on the site until 1.6.0 actually ships, but until then you can peruse the “raw” version of the docs in our Github repository. Some sample code is included therein as well as in the latest KitchenSink Facebook examples (search for “facebook” when you get there).

Authentication and Authorization

Our iOS and Android implementations both use Facebook’s OAuth 2.0 authentication scheme, as Facebook has deprecated all other forms of authentication. You don’t have to worry about any OAuth magic: we’re using Facebook’s official SDK for both iOS and Android, and it handles all that for us. You just need to either use our module’s Titanium.Facebook.authorize() method or you plop our Facebook LoginButton (Titanium.Facebook.createLoginButton()) on to your view and, when the user clicks it, we’ll handle calling authorize for you. Either way, you also need to set Titanium.Facebook.appid to your Facebook application id before initiating authorization. Also, if you need more than basic permissions, be sure to set the Titanium.Facebook.permissions property to an array of the permissions you need.

Android authentication looks pretty much the same as it always did: it pops up a dialog with a WebView that loads a facebook.com login page. In fact, this dialog comes entirely from Facebook’s own Android SDK, upon which we’ve built our module. As an alternative to this dialog, we also support Facebook’s “Single-Sign-On” (SSO), which will use the official, native Facebook Android application — if it’s installed — to walk the user through authorizing your application. You can read more about SSO in Facebook’s own mobile apps guide. We support SSO in both Android and iOS, however in our Android implementation we turn off SSO by default because things get a bit hairy if you don’t setup your Facebook app (not your mobile app, your Facebook app) perfectly to support SSO. If you’re sure everything is setup correctly and you want to enable SSO in your Titanium Android app, set Titanium.Facebook.forceDialogAuth to false (it is true by default, meaning it forces the dialog-based login fields rather than SSO via the Facebook phone app.)

iOS Facebook authentication in Titanium requires a bit more setup for devices that support multi-tasking. If the official iOS Facebook app is available on the device then authentication will occur via that app; this is the “Single-Sign-On” mentioned earlier. Otherwise, Safari is used. Either way, the authentication is done externally of your app, and is now entirely managed by Facebook. This means that your app will lose control of user interactions through the Facebook login process, but will immediately be reactivated upon the completion of the login process, at which time your login listeners will be fired. (Note that iOS devices that don’t support multi-tasking — and any device running a pre-4.0 OS — will automatically do authentication the “classic” way, via a window that appears inside your app.)

Because the iOS Facebook login process requires some additional information about how to restart your app from the Facebook application or Safari, you will need to make some changes to your tiapp.xml (or Info.plist) in addition to the changes to your app to match with the new API (more on that later). In particular:

  • If you use tiapp.xml:

    • Add in the following property:
      <property name="ti.facebook.appid">[YOUR FB APP ID GOES HERE]</property>
    • Clean and rebuild your app
    • Note that this property is ONLY to tell the Facebook authentication process
      how to restart your app: It does not tell the Titanium framework what your
      app ID is. You will still need to set the Titanium.Facebook.appid property.
  • If you use Info.plist:

    • You’ll need to edit the CFBundleURLSchemes array to include the URL that
      Facebook uses to restart your app after login is completed:

            <key>CFBundleURLSchemes</key>
            <array>
                    ... OTHER URL SCHEMES HERE ...
                    <string>fb[YOUR FB APP ID GOES HERE]</string>
            </array>
      

      Note the ‘fb’ prefix that goes before your Facebook app ID.

New Facebook API Methods

Beyond the changes to authentication discussed above, we’ve also gutted most of our old Titanium.Facebook methods and replaced them with APIs that better match Facebook’s most current native SDKs. If you’re familiar with modern Facebook mobile development outside of Titanium, then you know that there are generally three approaches to getting or submitting data from/to Facebook:

  • Graph API, which is what Facebook very much wants you to use instead of their…
  • REST API, which they now refer to as the “Old REST API”: a nice hint that you should be using the Graph API!

  • Dialogs, which are web-based dialog windows emanating from facebook.com.

  • Titanium now has analogs for each of these:

    • Use Titanium.Facebook.requestWithGraphPath(...) for Graph API calls.
  • Use Titanium.Facebook.request(...) for Old REST API calls.

  • Use Titanium.Facebook.dialog(...) to display official Facebook dialog windows.

  • The old Titanium.Facebook methods publishStream, query and execute are gone, but you can easily reproduce their behavior with our new methods. For example, the old query method performed FQL queries for you; you can do the same today with Titanium.Facebook.request("fql.query" ...) — see our KitchenSink example. Similarly, the fuctionality of the old publishStream method can be achieved via Titanium.Facebook.dialog("feed", ...) or, if you wish to publish directly without a dialog, use Titanium.Facebook.requestWithGraphPath("me/feed", ...) such as in the following code sample (a variation of which is also in KitchenSink):

    We expect our changes will lead to better integration of Facebook functionality with your Titanium-based applications. By more closely following the official Facebook mobile SDKs, we believe that we’ve made it easier for you to take what you learn from Facebook’s own documentation and apply it in Titanium.

    Code Strong!

    1 COMMENT

    1. This is great information and improvement, thank you!

      Question. Is Facebook’s SSO sign-on meant to take you out of your app to the Facebook app or Safari? Is there any way to force the legacy popup window instead of leaving the app? I haven’t seen many apps that take you out of the app to do a sign-on, and then back in. This could be disruptive and confusing to the user experience.

    2. Just a note that if you are doing SSO on Android you need to specify your key hash.

      You can do this by:

      1. Generating your key hash using SSL:
      keytool -exportcert -alias [ALIAS] -keystore [KEYSTORE]
      | openssl sha1 -binary
      | openssl base64

      2. Save your key under “Mobile & Devices” in the Facebook Developers App: http://www.facebook.com/developers

      The obvious gotcha here is that when you use Titanium to deploy to your device OR you’re using the emulator, you’re using a different key, ergo your “Key Hash” will be different. My advice is to generate your app via the “Distribute” tab, then use ADB and DDMS to debug.

    3. Thank you guys, but this approach is terrible.
      I agree with Bryce. In my opinion it would be better to open the normal popup.

    4. Thanks for the update! Love the new Graph stuff, just what i needed! However the new login doesnt feel good at all. I tried it out earlier today and jumping windows (either Safari or Facebook app) is not good. It can be confusing for the user and it makes the app feel a bit cheap if you ask me.

    5. I have a request. The new Facebook module sounds great unless a parent of an app meant for a younger demographic has “Restricted” Safari…essentially removing the app from the device(disabling or hiding it). WebViews are still functional, and so the option for the popup dialog is desirable to ensure proper functionality. At the very least your implementation should detect the “Restriction” of Safari and handle it gracefully. Currently apps just crash when Titanium.Facebook.authorize is called. We could also get by with a call which would detect the state of Safari and thus enabling us to remove the Facebook functionality when in the Restricted state.

    6. It is pretty straight forward to have a dialog to show up instead of safari web browser. You can simply comment lines “131-145 in Facebook.m”. Though, you will not benefit from the SSO capability and the user experience seem to be driven by Facebook and Titanium team.

      You can check out https://github.com/facebook/facebook-ios-sdk. The native plugin from facebook works the same like in Titanium.

    7. A tip for those who, like me, think that throwing our users out of our app to do the Facebook auth looks unprofessional:

      You can edit FBConnect/Facebook.m line 214 (in 1.6.0RC1 – it’s the authorizeWithFBAppAuth line in the authorize:permissions:delegate: method) to read `[self authorizeWithFBAppAuth:NO safariAuth:NO];` and then erase the contents of the build/iphone dir in your Titanium project (make sure not to erase the iphone dir, just erase all of its contents) to force a full build.

      From then on, Facebook’s SSO will be disabled and you’ll get the old dialog-based login. It’s unfortunate that Appcelerator didn’t see fit to give us control over this on iOS (they did on Android) but hopefully they’ll offer such an option in a future version.

    8. Is there anything else we need to set up on the facebook side?

      I’ve followed every step in this doc, added the property line to the tiapp.xml and i still get the “Safari cannot open the page because the address is invalid” message.

      Not sure what to do anymore. I’m pretty sure that it’s something on the facebook side because if i change the API ID to the appcelerator one, it works.

      Thanks
      Raf

    9. I did what Jonathan suggested along with what appcelerator suggested with the ti.xml file. However I added changed line 207 in FBConnect/Facebook.m from: _appId = [application_id copy]; to _appID = @”MY APP ID”; and SUCCESS! it works inside the app with a dialog

    10. actually, scratch the above.

      Line 207: _appId = @”MY APP ID”;
      Line 214 should be [self authorizeWithFBAppAuth:YES safariAuth:NO];

      Along with adding in: MY APP ID to tiapp.xml

      REbuild via xcode, and it works.

    11. actually, scratch the above.

      Line 207: _appId = @”MY APP ID”;
      Line 214 should be [self authorizeWithFBAppAuth:NO safariAuth:NO];

      Along with adding in: MY APP ID to tiapp.xml

      REbuild via xcode, and it works.