Not too long ago I contributed to the ng-cordova project on GitHub. I added Oauth functionality to many popular API providers such as Google, Facebook, and Twitter.
I made a guide on how to use this added Oauth functionality on the official Ionic Framework blog, but since then I’ve received a good deal of requests to take it a step further and actually use on of the APIs beyond just Oauth.
This tutorial will help you better understand how to use the Facebook APIs for use in your Phonegap or Ionic Framework mobile application.
Let’s start by creating a fresh Ionic Framework Android and iOS application:
ionic start FacebookApp blank
cd FacebookApp
ionic platform add android
ionic platform add ios
Remember, if you’re not using a Mac, you cannot add and build for the iOS platform.
There are two requirements to this project. You must include the ngCordova library for $cordovaOauth
and the Apache Cordova InAppBrowser plugin. If you aren’t familiar with the InAppBrowser plugin, I suggest you read about it in one of my previous posts. I also suggest you read about $cordovaOauth
via the official Ionic Framework blog.
Start by installing the InAppBrowser plugin. This can be accomplished by running the following from the Terminal or command prompt:
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-inappbrowser.git
With the plugin installed, grab the latest ngCordova release and extract ng-cordova.min.js into your project’s www/js directory.
With the file in place, open your www/index.html file and include the library like so:
<script src="js/ng-cordova.min.js"></script>
It is very important that this include goes before the cordova.js
line, otherwise you’re going to get strange results.
One final thing needs to happen before we can start using ngCordova in our project. We need to inject it into our angular.module
directives. This can be done like the following in your www/js/app.js file:
var facebookApp = angular.module("starter", ["ionic", "ngCordova"]);
Because we like keeping things slick and easy, we’re also going to include ngStorage into our project. More information on this library can be seen in one of my previous posts on the topic. Download and include the library into your project.
Our Facebook project is going to be composed of the following three screens managed by the AngularJS UI-Router:
Let’s start by adding the following code to our login template:
<ion-view title="Facebook Example">
<ion-content>
<div class="padding">
<button ng-click="login()" class="button button-block button-balanced">Oauth Sign In</button>
<p>
Clicking the above button will initiate an official browser sign in flow with Facebook. You
will be redirected to the Facebook website to enter your credentials.
</p>
</div>
</ion-content>
</ion-view>
The only purpose the above template serves is to launch the InAppBrowser for the Oauth login flow. The controller code can be demonstrated with the following:
facebookApp.controller("LoginController", function($scope, $cordovaOauth, $localStorage, $location) {
$scope.login = function() {
$cordovaOauth.facebook("CLIENT_ID_HERE", ["email", "read_stream", "user_website", "user_location", "user_relationships"]).then(function(result) {
$localStorage.accessToken = result.access_token;
$location.path("/profile");
}, function(error) {
alert("There was a problem signing in! See the console for logs");
console.log(error);
});
};
});
Notice that after a successful login, the access token is saved and we are redirected to our profile. The access token will be used in every future API request for the application.
Let’s take a look at the profile template. Add the following code to your www/templates/profile.html file:
<ion-view title="Profile" ng-init="init()">
<ion-content>
<div class="list card">
<div class="item item-avatar">
<img ng-src="{{profileData.picture.data.url}}">
<h2>{{profileData.name}}</h2>
<p>{{profileData.id}}</p>
</div>
<a href="#" class="item item-icon-left">
<i class="icon ion-earth"></i>
{{profileData.website}}
</a>
<a href="#" class="item item-icon-left">
<i class="icon ion-home"></i>
{{profileData.location.name}}
</a>
<a href="#" class="item item-icon-left">
<i class="icon ion-heart"></i>
{{profileData.relationship_status}}
</a>
</div>
</ion-content>
</ion-view>
On the profile screen we will display the signed in users name, avatar, website, location, and relationship status. There is plenty more data to choose from, but we’re keeping it simple in this example. The controller to populate this data can be seen below:
facebookApp.controller("ProfileController", function($scope, $http, $localStorage, $location) {
$scope.init = function() {
if($localStorage.hasOwnProperty("accessToken") === true) {
$http.get("https://graph.facebook.com/v2.2/me", { params: { access_token: $localStorage.accessToken, fields: "id,name,gender,location,website,picture,relationship_status", format: "json" }}).then(function(result) {
$scope.profileData = result.data;
}, function(error) {
alert("There was a problem getting your profile. Check the logs for details.");
console.log(error);
});
} else {
alert("Not signed in");
$location.path("/login");
}
};
});
You can see in the above code that we are making use of the /me API endpoint which is documented here. You’ll notice that we are passing the stored access token with the request. Without it, Facebook won’t be able to validate us.
The final screen we’ll be looking at is the news feed. Open your www/templates/feed.html file and include the following code:
<ion-view title="Feed" ng-init="init()">
<ion-content>
<div ng-repeat="data in feedData">
<div class="list card" ng-if="data.hasOwnProperty('message')">
<div class="item item-avatar">
<img ng-src="{{feedData.myPicture}}">
<h2>{{data.from.name}}</h2>
<p>{{data.created_time}}</p>
</div>
<div class="item item-body">
<p>
{{data.message}}
</p>
<p>
<a href="#" class="subdued">{{data.likes.data.length}} Likes</a>
<a href="#" class="subdued">{{data.comments.data.length}} Comments</a>
</p>
</div>
<div class="item tabs tabs-secondary tabs-icon-left">
<a class="tab-item" href="#">
<i class="icon ion-thumbsup"></i>
Like
</a>
<a class="tab-item" href="#">
<i class="icon ion-chatbox"></i>
Comment
</a>
<a class="tab-item" href="#">
<i class="icon ion-share"></i>
Share
</a>
</div>
</div>
</div>
</ion-content>
</ion-view>
Posts to the feed will display in a similar fashion to the official Facebook application. They will appear in one card, per post. The controller code to go with this template can be seen below:
facebookApp.controller("FeedController", function($scope, $http, $localStorage, $location) {
$scope.init = function() {
if($localStorage.hasOwnProperty("accessToken") === true) {
$http.get("https://graph.facebook.com/v2.2/me/feed", { params: { access_token: $localStorage.accessToken, format: "json" }}).then(function(result) {
$scope.feedData = result.data.data;
$http.get("https://graph.facebook.com/v2.2/me", { params: { access_token: $localStorage.accessToken, fields: "picture", format: "json" }}).then(function(result) {
$scope.feedData.myPicture = result.data.picture.data.url;
});
}, function(error) {
alert("There was a problem getting your profile. Check the logs for details.");
console.log(error);
});
} else {
alert("Not signed in");
$location.path("/login");
}
};
});
The feed screen makes use of the /me/feed API endpoint. Again, we are passing the access token with the request.
Facebook has a ton of API documentation. Unlike other services, this documentation is helpful. This full and working project can be forked on GitHub if you’d like to see it in action. It also includes minor bits an pieces that I’ve specifically chosen not to include in this write-up, such as the use of tabs.