Page tree
Skip to end of metadata
Go to start of metadata

This guide explains how to consume Twitter REST APIs in a Smartface app. Sample codes are taken from Smartface in Action App.

About Twitter APIs and The Auth Flow

The REST APIs provide programmatic access to read and write Twitter data. You can author a new Tweet, read profiles, follower data etc. if you have authenticated. The REST API identifies Twitter applications and users using OAuth and returns JSON. Therefore, Twitter REST API services can be simply connected via XMLHttpRequest object.

As you are developing a brand new mobile app that consumes Twitter APIs, you need to read "Application-only authentication" and follow "Auth Flow" as Twitter expected.

  • An application encodes its consumer key and secret into a specially encoded set of credentials.
  • An application makes a request to the POST oauth2 / token endpoint to exchange these credentials for a bearer token.
  • When accessing the REST API, the application uses the bearer token to authenticate.

Create Twitter App

To consume Twitter APIs, Twitter needs us to create a new Twitter App on Twitter Developer Center.

Set the variables

After creating your Twitter App, you will find your "Consumer Key (API Key)" and "Consumer Secret (API Secret)" on "Keys and Access Tokens" page. We'll use these keys to authenticate Twitter REST API services. 

Before accessing Twitter API, we are adding our keys on top of the workspace.

	//API URLs
	var TwitterBearerTokenURL = "https://api.twitter.com/oauth2/token";
	var TwitterStreamURL = "https://api.twitter.com/1.1/statuses/user_timeline.json?count=20&screen_name=smartface_io";
	
	var CONSUMER_KEY = "YOUR CONSUMER KEY"; //put your app's consumer token here
	var CONSUMER_SECRET = "YOUR CONSUMER SECRET"; //put your app's consumer secret here

	//Encode Consumer Key and Consumer Secret in Base64 format
	var encodedBase64 = btoa(CONSUMER_KEY + ":" + CONSUMER_SECRET);

Fetch Twitter Bearer Token

XMLHttpRequest object makes sending HTTP requests very easy. We'll use it to fetch Twitter data from REST APIs. For more information about Twitter REST API, please see the Twitter Official documentations.

As it mentioned in "Auth Flow" above we'll first get the bearer token from oauth2/token endpoint, then we'll create another XHR to populate tweets from statuses/user_timeline

   /*
	Please read Twitter's application only auth flow "https://dev.twitter.com/oauth/application-only" first
	The application-only auth flow follows these steps:

	An application encodes its consumer key and secret into a specially encoded set of credentials.
	An application makes a request to the POST oauth2 / token endpoint to exchange these credentials for a bearer token.
	When accessing the REST API, the application uses the bearer token to authenticate.
	*/

	//We're getting the bearer token from https://api.twitter.com/oauth2/token
	function getTwitterBearerToken() {
		//creating new XHR to get token
		var xhrGetTwitterBearerToken = new XMLHttpRequest();

		xhrGetTwitterBearerToken.onload = onGetTwitterBearerTokenSyndicationSuccess; //call it on success
		xhrGetTwitterBearerToken.onError = onGetTwitterBearerTokenSyndicationError; //call it on error
		xhrGetTwitterBearerToken.timeout = 120;
		xhrGetTwitterBearerToken.open("POST", TwitterBearerTokenURL);

		//adding auth header to the request
		xhrGetTwitterBearerToken.setRequestHeader("Authorization", "Basic " + encodedBase64);
		xhrGetTwitterBearerToken.setRequestHeader("User-Agent", "SmartfaceTwitterRestApi");
		xhrGetTwitterBearerToken.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");

		//requesting token by sending grand_type=credentials
		xhrGetTwitterBearerToken.send("grant_type=client_credentials");
	}
 
	//if there is an error during syndication, we'll raise an alert
	function onGetTwitterBearerTokenSyndicationError(e) {
		alert(JSON.stringify(e));
	}

Request User's Timeline

If getTwitterBearerToken is success we'll extract token from it's responseText and use it in a new XHR to get Tweets from the API.

   
	//parsing the XHR result.
	function onGetTwitterBearerTokenSyndicationSuccess() {
		//getting response text and parsing it
		var parsedResponse = JSON.parse(this.responseText);

		// extracting access_token
		var token = parsedResponse.access_token;
		var token_type = parsedResponse.token_type;

		if ((token) && (token_type)) {
			//creating new XHR to get tweets
			var xhrGetTweetList = new XMLHttpRequest();
			xhrGetTweetList.onload = onGetTweetListSyndicationSuccess; //call it on success
			xhrGetTweetList.onError = onGetTweetListSyndicationError; //call it on error

			xhrGetTweetList.timeout = 120;
			xhrGetTweetList.open("GET", TwitterStreamURL);
			//adding auth header to the request 
			xhrGetTweetList.setRequestHeader("Authorization", token_type + " " + token);
			xhrGetTweetList.setRequestHeader("Content-Type", "application/json");

			//getting tweets
			xhrGetTweetList.send();
		}
		else {
			alert('Token or token_type is empty please try it again.');
		}
	}

Display Tweets in a RepeatBox

As we've made our request for tweets, now we have our response. We'll parse it and put all tweets in a RepeatBox object.

	//parsing the XHR result.
	function onGetTweetListSyndicationSuccess() {
		var parsedResponse = JSON.parse(this.responseText);
		var arrayTweets = [];

		for (var i = 0; i < parsedResponse.length; i++) {
			var objTwitter = {};
			objTwitter.name = parsedResponse[i].user.name;
			objTwitter.screen_name = '@' + parsedResponse[i].user.screen_name;
			//getting bigger profile image
			//check https://dev.twitter.com/overview/general/user-profile-images-and-banners
			objTwitter.profileImage = parsedResponse[i].user.profile_image_url_https.replace('_normal', '');
			objTwitter.text = parsedResponse[i].text;
			arrayTweets.push(objTwitter);
		}

		//creating a repeatbox to show tweets as a list
		var rptBoxTweets = new SMF.UI.RepeatBox({
			top: '0%',
			left: '0%',
			width: '100%',
			height: '100%',
			showScrollbar: true,
			fillColor: "#3B3B3B"
		});

		//tweet profile image
		var imageProfile = new SMF.UI.Image({
			top: '0%',
			left: '0%',
			width: '30%',
			height: '100%',
			imageFillType: SMF.UI.ImageFillType.ASPECTFIT
		});

		//user name
		var labelName = new SMF.UI.Label({
			top: '5%',
			left: '31%',
			width: '30%',
			height: '10%',
			multipleLine: false,
			touchEnabled: false,
			font: new SMF.UI.Font({
				size: '6pt',
				bold: true
			})
		});

		//user screen_name
		var labelScreenName = new SMF.UI.Label({
			top: '5%',
			left: '61%',
			width: '49%',
			height: '10%',
			multipleLine: false,
			touchEnabled: false,
			font: new SMF.UI.Font({
				size: '5pt',
				bold: false,
				color: SMF.UI.Color.DARKGRAY
			})
		});

		//tweet title
		var labelTweet = new SMF.UI.Label({
			top: '15%',
			left: '31%',
			width: '68%',
			height: '85%',
			multipleLine: true,
			touchEnabled: false,
			font: new SMF.UI.Font({
				size: '7pt'
			})
		});

		//adding image and tweet text to repeatbox's itemtemplate
		rptBoxTweets.itemTemplate.height = Device.screenHeight / 6;
		rptBoxTweets.itemTemplate.add(imageProfile);
		rptBoxTweets.itemTemplate.add(labelName);
		rptBoxTweets.itemTemplate.add(labelScreenName);
		rptBoxTweets.itemTemplate.add(labelTweet);

		//onRowRender will work for each item bound
		rptBoxTweets.onRowRender = function(e) {
			this.controls[0].image = arrayTweets[e.rowIndex].profileImage;
			this.controls[1].text = arrayTweets[e.rowIndex].name;
			this.controls[2].text = arrayTweets[e.rowIndex].screen_name;
			this.controls[3].text = arrayTweets[e.rowIndex].text;
		};

		//binding Tweet array
		rptBoxTweets.dataSource = arrayTweets;
		rptBoxTweets.refresh();

		//adding repeatbox to the page
		page1.add(rptBoxTweets);
	}

Don't forget to call getTwitterBearerToken() within page1_onShow() event.

Run on Device

Now we're ready to run it on the device