Error
  • Copy failed
28November

Facebook - FQL - Page Friend Likes

Facebook - FQL - Page Friend Likes

For the new project I currently working on, I need to focus on Facebook's Android SDK in more detail as I did in the past. A couple of months ago I had to integrate Facebook functionalities like login/logout, image uploading and status posting for the Next Liberty Theatre - Photo Component - it was not a big throw. In this new project the general focus is on lcoation-based augmented reality in combination with social media like Facebook.

 

Facebook Graph API And FQL Introduction

For those who have never ever worked with the Facebook SDK, I will try to provide a short overview about the social graph and its SDK. At Facebook's core is the social graph which reflects all the users, pages and objects and their connections to each other and everything they care about. To access this social graph, Facebook's developer have designed and implemented the graph API. The graph API represents a quite simple view of this social graph and enables the developer to access all necessary information e.g. the user's information, his connections to friends or other objects. As an example, here is the result of a graph API query in this case from the Coca Cola Facebook page.
Besides the graph API there exists another way how Facebook's social graph can be accessed and farmed, FQL - Facebook Query Langauge. This language is strongly orientated on SQL however there are a couple of features missing e.g. JOINs. Nevertheless the FQL is a quite powerful tool to get some information out of Facebook.


To secure the user's privacy and prohibt the absue of private information, Facebook has implemented different kind of security mechanisms e.g. App registration, oAuth2.0 etc. Moreover there is also a public interface that can be queried without the need of authentication.

 

The Challenge And The Solution

One part of the project is finding all friends who have liked some special pages, let's take Coca Cola again - for those who impute me to be sponsored by Coke, no I don't even like this stuff ^^. In my cirlce of friends there are only three guys who have liked the Coca Cola site.

 

First Approach - Facebook Graph API

So the first approach I have found worked indeed, however the performance on a mobile device was quite lousy. In this approach it was necessary to query the user's friend list to get all his friends, afterwards each friend needs to be checked if he has liked the specific page. I have heart there are users out there who have 500 friends and more. For my friendlist with about 150 friends the request took between three and eight seconds.

FriendsListRequestListener is the first callback function that is called after retrieving the friends list

        
        Button friendLikesButton = new Button(this);
        friendLikesButton.setText("friends page likes");
        friendLikesButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	String text = "/me/friends";
            	mAsyncRunner.request(text, new FriendsListRequestListener());
            }
        });

 

Callback funtion for the friendlist request

public class FriendsListRequestListener implements RequestListener {

        public void onComplete(String response, final Object state) {
        	
        	webView.loadData(response, "text/html", null);
        	
        	try {
        		startTime = System.currentTimeMillis();
                JSONObject json = Util.parseJson(response);
                JSONArray friends = json.getJSONArray("data");
                pageFriendLikesCount = currentFriendsCount = 0;
                friendsCount = friends.length();
                Log.e("friendsCount",String.valueOf(friendsCount));
                for ( int i=0; i<friendsCount; ++i )
                {
                	JSONObject json_obj = friends.getJSONObject(i);
                	String name = json_obj.getString("name");
                	String id = json_obj.getString("id");
                	//40796308305= coca-cola
                	String text = "/"+id+"/likes/40796308305";
                	mAsyncRunner.request(text, new FriendsLikesRequestListener());
                }                
                
        	} catch (JSONException e) {
                Log.e("stream", "JSON Error:" + e.getMessage());
            } catch (FacebookError e) {
                Log.e("stream", "Facebook Error:" + e.getMessage());
            }
        }

        public void onFacebookError(FacebookError e, final Object state) {
            Log.e("stream", "Facebook Error:" + e.getMessage());
        }

        public void onFileNotFoundException(FileNotFoundException e,
                                            final Object state) {
            Log.e("stream", "Resource not found:" + e.getMessage());      
        }

        public void onIOException(IOException e, final Object state) {
            Log.e("stream", "Network Error:" + e.getMessage());      
        }

        public void onMalformedURLException(MalformedURLException e,
                                            final Object state) {
            Log.e("stream", "Invalid URL:" + e.getMessage());            
        }

    }

 

Callback funtion for the page ID queryed by each friend of the list

public class FriendsCountRequestListener implements RequestListener {

        public void onComplete(String response, final Object state) {
        	
        	webView.loadData(response, "text/html", null);
        	
        	try {
        		String data = "{ \"data\": ";
        		String newVal = data + response + "}";
                JSONObject json = Util.parseJson(newVal);
                JSONArray likes = json.getJSONArray("data");
                friendsCount = likes.length();
                Log.e("FriendsCountRequestListener",String.valueOf(friendsCount)+" friends");  
                timeDiff = System.currentTimeMillis() - startTime;
                showMessage(String.valueOf(friendsCount)+" friends");
        	} catch (JSONException e) {
                Log.e("stream", "JSON Error:" + e.getMessage());
            } catch (FacebookError e) {
                Log.e("stream", "Facebook Error:" + e.getMessage());
            }
        }

        public void onFacebookError(FacebookError e, final Object state) {
            Log.e("stream", "Facebook Error:" + e.getMessage());
        }

        public void onFileNotFoundException(FileNotFoundException e,
                                            final Object state) {
            Log.e("stream", "Resource not found:" + e.getMessage());      
        }

        public void onIOException(IOException e, final Object state) {
            Log.e("stream", "Network Error:" + e.getMessage());      
        }

        public void onMalformedURLException(MalformedURLException e,
                                            final Object state) {
            Log.e("stream", "Invalid URL:" + e.getMessage());            
        }

    }

 

 

Second Approach -  FQL

Driven by this unsatisfying result I started searching again and finally I have found this really great approach with a query time between 200 and 700 milliseconds, so there is a performance boost by factor 10. People working with databases are aware by the power of SQL and FQL works quite similar.

 

Button execution implementation with FQL implementation

Button friendsLikesFQLButton = new Button(this);
        friendsLikesFQLButton.setText("friends page likes");
        friendsLikesFQLButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	textField.setText(kravMagaPageId);
            	String fqlQuery = "SELECT first_name, last_name FROM user WHERE uid IN ( SELECT uid FROM page_fan WHERE page_id='"+kravMagaPageId+"' AND uid IN ( SELECT uid2 FROM friend WHERE uid1 = me() ) )";
            	Bundle params = new Bundle();
            	params.putString("method", "fql.query");
            	params.putString("query", fqlQuery);
            	mAsyncRunner.request(params, new FriendsLikes2RequestListener());
            }
        }); 

 

Callback function implementation of page likes request

public class FriendsLikes2RequestListener implements RequestListener {

        public void onComplete(String response, final Object state) {
        	try {
        		String data = "{ \"data\": ";
        		String newVal = data + response + "}";
                JSONObject json = Util.parseJson(newVal);
                JSONArray likes = json.getJSONArray("data");
                pageFriendLikesCount = likes.length();
                Log.e("FriendsLikes2RequestListener","--------- done - page was liked by "+String.valueOf(pageFriendLikesCount)+" friends---------");  
                timeDiff = System.currentTimeMillis() - startTime;
                showMessage(String.valueOf(timeDiff)+" ms");
            } catch (JSONException e) {
                Log.e("stream", "JSON Error:" + e.getMessage());
            } catch (FacebookError e) {
                Log.e("stream", "Facebook Error:" + e.getMessage());
            }
        }

        public void onFacebookError(FacebookError e, final Object state) {
            Log.e("stream", "Facebook Error:" + e.getMessage());
        }

        public void onFileNotFoundException(FileNotFoundException e,
                                            final Object state) {
            Log.e("stream", "Resource not found:" + e.getMessage());      
        }

        public void onIOException(IOException e, final Object state) {
            Log.e("stream", "Network Error:" + e.getMessage());      
        }

        public void onMalformedURLException(MalformedURLException e,
                                            final Object state) {
            Log.e("stream", "Invalid URL:" + e.getMessage());            
        }
    }

 

 

I hope this article is not to confusing, it was quite late and I had already some lack of concentration ^^


I'm looking forward to get some comments or hints.

 

cheers,
Chris

Posted in Blog, Android

Comments (0)

Leave a comment

You are commenting as guest. Optional login below.