Rendering photos and videos from Facebook news feed in Android application

In the last post, I described how to get photos and videos from a user’s Facebook news feed. In this post, I will continue on and describe how to build a simple user interface for showing these photos and videos for an Android app. Let’s have a look at how this is going to look like:

Let us first build a model that would describe the main parts of data that we obtained from the fql queries. We will extract the main parts in the media objects as follows:

if (mediaResultObject.has("attachment") && mediaResultObject.getJsonObject("attachment").has("media")) {
	// Get attachment name and href
	String attachmentName = Utils.getStringFromJsonIfExists(mediaResultObject.getJsonObject("attachment"),
			"name");
	final String attachmentHref = Utils.getStringFromJsonIfExists(
			mediaResultObject.getJsonObject("attachment"), "href");

	// Get id of actor who posted the content
	String actorId = mediaResultObject.getString("actor_id");
	String postId = mediaResultObject.getString("post_id");
	String createdTime = mediaResultObject.getString("created_time");

	JsonArray mediaArray = mediaResultObject.getJsonObject("attachment").getJsonArray("media");
	for (int i = 0; i < mediaArray.length(); ++i) {
		final JsonObject mediaObject = mediaArray.getJsonObject(i);

		String type = mediaObject.getString("type");

		// Get thumbnail url
		String thumbnailUrl = Utils.getStringFromJsonIfExists(mediaObject, "src");

		MediaPost post = new MediaPost(attachmentName, attachmentHref, actorId, postId, createdTime, type,
				thumbnailUrl);

		String fbid = null;
		if (type.equals("photo") && mediaObject.has("photo")) { // Photo
			fbid = mediaObject.getJsonObject("photo").getString("fbid");
		} else if (mediaResultObject.getJsonObject("attachment").has("fb_object_id")) {
			fbid = mediaResultObject.getJsonObject("attachment").getString("fb_object_id");
		}
		post.setHref(mediaObject.getString("href"));
		post.setFbId(fbid);
		post.setMediaObject(mediaObject);
		post.setAlt(mediaObject.getString("alt"));

		posts.add(post);
	}
}

The mediaObject here is a jsonObject parsed from a json object like so:

{
  "actor_id": 202209223157016,
  "created_time": 1357059211,
  "likes": {
    "href": "https://www.facebook.com/browse/likes/?id=501300199914582",
    "count": 13,
    "sample": [
      100001172558908,
      202209223157016,
      100002876441601
    ],
    "friends": [
      100000185344749
    ],
    "user_likes": false,
    "can_like": true
  },
  "post_id": "202209223157016_501300213247914",
  "attachment": {
    "media": [
      {
        "href": "https://www.facebook.com/photo.php?fbid=501300199914582&set=a.202685659776039.53449.202209223157016&type=1&relevant_count=1",
        "alt": "I am alone but not dead ... rnrnrn~ Alone Tree Silhouette at Railay Beach",
        "type": "photo",
        "src": "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-prn1/12594_501300199914582_1535726991_s.jpg",
        "photo": {
          "aid": "202209223157016_53449",
          "pid": "202209223157016_1613061",
          "fbid": 501300199914582,
          "owner": 202209223157016,
          "index": 1,
          "width": 634,
          "height": 1024
        }
      }
    ],
    "name": "",
    "caption": "",
    "description": "",
    "properties": [
    ],
    "icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yz/r/StEh3RhPvjk.gif",
    "fb_object_type": "photo",
    "fb_object_id": "202209223157016_1613061"
  }
}

Here’s the layout we will use for each object:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/gradient_background_gray"
    android:paddingLeft="5dp"
    android:paddingRight="5dp" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:src="@drawable/abs__ab_bottom_solid_dark_holo" >
    </ImageView>

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:background="@color/TranslucentBlack"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/attachment_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:gravity="center_horizontal"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="@color/facebookName"
            android:textStyle="bold" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:background="@color/TranslucentBlack"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/picture_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:ellipsize="end"
            android:gravity="center_horizontal"
            android:maxLines="3"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="@color/WhiteSmoke" />

        <TextView
            android:id="@+id/user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Medium Text"
            android:textColor="@color/facebookName"
            android:layout_gravity="right"
            android:textAppearance="?android:attr/textAppearanceSmall" />
    </LinearLayout>

    <ImageButton
        android:id="@+id/playButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_play" />

</RelativeLayout>

We will use a custom PagerAadpter to render each item in the page. Here’s the function that would then instantiate each view in the PagerAdapter.

public Object instantiateItem(View collection, int position) {
	LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(
			Context.LAYOUT_INFLATER_SERVICE);
	View view = inflater.inflate(R.layout.view_image_photo, null);
	final MediaPost post = posts.get(position);

	String thumbnailUrl = post.getThumbnailUrl();

	if (post.getType().equals("video")) {
		// Overlay play button and handle click.
		ImageButton imageButton = (ImageButton) view.findViewById(R.id.playButton);
		imageButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				playVideo(post.getMediaObject().getJsonObject("video"));
			}
		});
	} else if (post.getType().equals("photo")) {
		// Hide play button
		view.findViewById(R.id.playButton).setVisibility(View.GONE);

		// Get better thumbnail url.
		thumbnailUrl = "https://graph.facebook.com/" + post.getFbId() + "/picture?type=normal&access_token="
				+ accessToken;
	}

	// Load thumbnail image in image view
	if (thumbnailUrl != null) {
		ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
		imageLoader.DisplayImage(thumbnailUrl, imageView, false);
	}

	// Add details above and below
	TextView mediaName = (TextView) view.findViewById(R.id.picture_title);
	TextView attachmentNameTextView = (TextView) view.findViewById(R.id.attachment_name);
	TextView userNameTextView = (TextView) view.findViewById(R.id.user_name);

	// Set user name or hide view.
	if (post.getActorId() != null) {
		userNameTextView.setText(users.get(post.getActorId()).getString("name"));
	} else {
		userNameTextView.setVisibility(View.GONE);
	}

	mediaName.setText(post.getAlt());
	if (post.getAttachmentName() != null && post.getAttachmentName().length() > 0) {
		attachmentNameTextView.setText(post.getAttachmentName());
		if (post.getAttachmentHref() != null) {
			((View) attachmentNameTextView.getParent()).setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(post.getAttachmentHref()));
					context.startActivity(browserIntent);
				}
			});
		}
	} else {
		attachmentNameTextView.setVisibility(View.GONE);
	}

	((ViewPager) collection).addView(view, 0);
	return view;
}

Playing the video from the url on Android can be a bit tricky. One thing that I found about streaming videos on Android is that it is difficult to stream videos with url beginning with https. Fortunately, for the videos that we receive from facebook, just converting the urls to http works fine. Here’s how you would play the video in the default media player in android.

protected void playVideo(JsonObject video) {
	String videoUrl = Utils.getStringFromJsonIfExists(video, "source_url");
	try {
		if (videoUrl.startsWith("https")) {
			videoUrl = "http" + videoUrl.substring(5);
		}
		// First try to obtain correct mime type and play video.
		Intent intent = new Intent(Intent.ACTION_VIEW);
		String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(videoUrl);
		String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
		intent.setDataAndType(Uri.parse(videoUrl), mimetype);
		context.startActivity(intent);
	} catch (ActivityNotFoundException e) {
		// Unable to play using mime type.
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(Utils.getStringFromJsonIfExists(video, "display_url")));
		context.startActivity(intent);
	}

}

We are almost done. Now we just need to create a ViewPager and set the adapter. Create the view pager in the layout and then get the reference to the ViewPager in your Activity/Fragment and set the subclass of PagerAdapter you just created.

<android.support.v4.view.ViewPager
  android:id="@+id/viewPager"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />
Published 3 Jan 2013

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter