com.bloc.blocparty.TimelineFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.bloc.blocparty.TimelineFragment.java

Source

/**
 * Copyright 2010-present Facebook.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bloc.blocparty;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;

import com.facebook.FacebookRequestError;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionDefaultAudience;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphObject;
import com.facebook.model.GraphUser;
import com.facebook.widget.FacebookDialog;
import com.facebook.widget.ProfilePictureView;

/**
 * Fragment that represents the main timeline screen for BlocParty.
 */
public class TimelineFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

    private static final String TAG = "TimelineFragment";
    private static final String PENDING_ANNOUNCE_KEY = "pendingAnnounce";
    private static final Uri M_FACEBOOK_URL = Uri.parse("http://m.facebook.com");
    private static final int REAUTH_ACTIVITY_CODE = 100;
    private static final String PERMISSION = "publish_actions";

    private static final int RESULT_CANCELED = 0;
    private static final int RESULT_OK = -1;

    private static final int PHOTO_SUBMIT = 2;

    private Uri fileUri;

    String mCurrentPhotoPath = "";

    private TextView announceButton;
    private TextView messageButton;
    private TextView titleText;
    private ListView listView;
    private List<BaseListElement> listElements;
    private ProfilePictureView profilePictureView;
    private boolean pendingAnnounce;
    private BlocParty blocParty;
    private Uri photoUri;
    private ArrayList<PhotoPost> photoArray;
    private SwipeRefreshLayout swipeLayout;

    private UiLifecycleHelper uiHelper;
    private Session.StatusCallback sessionCallback = new Session.StatusCallback() {
        @Override
        public void call(final Session session, final SessionState state, final Exception exception) {
            onSessionStateChange(session, state, exception);
        }
    };
    private FacebookDialog.Callback nativeDialogCallback = new FacebookDialog.Callback() {
        @Override
        public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) {
            boolean resetSelections = true;
            if (FacebookDialog.getNativeDialogDidComplete(data)) {
                if (FacebookDialog.COMPLETION_GESTURE_CANCEL
                        .equals(FacebookDialog.getNativeDialogCompletionGesture(data))) {
                    // Leave selections alone if user canceled.
                    resetSelections = false;
                    showCancelResponse();
                } else {
                    showSuccessResponse(FacebookDialog.getNativeDialogPostId(data));
                }
            }

            if (resetSelections) {
                init(null);
            }
        }

        @Override
        public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) {
            new AlertDialog.Builder(getActivity()).setPositiveButton(R.string.error_dialog_button_text, null)
                    .setTitle(R.string.error_dialog_title).setMessage(error.getLocalizedMessage()).show();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        blocParty = (BlocParty) getActivity();
        uiHelper = new UiLifecycleHelper(getActivity(), sessionCallback);
        uiHelper.onCreate(savedInstanceState);

        photoArray = new ArrayList<PhotoPost>();
    }

    @Override
    public void onResume() {
        super.onResume();
        uiHelper.onResume();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_timeline, container, false);

        swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container);
        swipeLayout.setOnRefreshListener(this);
        profilePictureView = (ProfilePictureView) view.findViewById(R.id.selection_profile_pic);
        profilePictureView.setCropped(true);
        announceButton = (TextView) view.findViewById(R.id.announce_text);
        messageButton = (TextView) view.findViewById(R.id.message_text);
        listView = (ListView) view.findViewById(R.id.picture_list);
        titleText = (TextView) view.findViewById(R.id.title_text);
        titleText.setTypeface(BlocParty.MUSEO_700);

        /*
         * if (FacebookDialog.canPresentOpenGraphMessageDialog(blocParty)) {
         * messageButton.setVisibility(View.VISIBLE); }
         */

        // init(savedInstanceState);

        Session session = Session.getActiveSession();
        if (session != null && session.isOpened()) {
            /*
             * List<String> permissions = Arrays.asList("publish_action");
             * Session.NewPermissionsRequest newPerm = new
             * Session.NewPermissionsRequest(this, permissions);
             * session.requestNewPublishPermissions(newPerm);
             */
            makeMeRequest(session);
        }

        return view;
    }

    Bitmap bm;

    // For main TimelineFragment
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK && requestCode >= 0 /*
                                                                 * &&
                                                                 * requestCode <
                                                                 * listElements
                                                                 * .size()
                                                                 */) {
            Log.d(TAG, "photo submit button pressed");
            uploadPhoto();
        } else { // This means to re-authenticate
            uiHelper.onActivityResult(requestCode, resultCode, data, nativeDialogCallback);
        }

        // For camera
        if (requestCode == CAMERA_TAKE_PHOTO_REQUEST_CODE) {
            if (resultCode == RESULT_OK) { // -1
                // successfully captured the image
                // display it in image view
                bm = BitmapFactory.decodeFile(mCurrentPhotoPath);

                try {

                    if (fileUri != null) {
                        photoUri = fileUri;
                        Log.d(TAG, "Image saved to:\n" + photoUri);
                        Log.d(TAG, "Image path:\n" + photoUri.getPath());
                        Log.d(TAG, "Image name:\n" + photoUri.getLastPathSegment());// getName(fileUri));

                        PictureSubmitFragment picSubmitFragment = new PictureSubmitFragment();
                        picSubmitFragment.setSubmitPhotoAndFileName(bm, photoUri);
                        picSubmitFragment.setTargetFragment(this, PHOTO_SUBMIT);
                        picSubmitFragment.show(getFragmentManager(), "fragment_picture_submit");

                    } else if (data != null) {
                        photoUri = data.getData();
                    } else if (resultCode == RESULT_CANCELED) { // 0
                        // user cancelled Image capture

                    } else {
                        // failed to capture image

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void uploadPhoto() {
        Bundle params = new Bundle();
        params.putParcelable("source", bm);
        // params.putString("source-comments", "comments");
        /* make the API call */
        new Request(Session.getActiveSession(), "/me/photos", params, HttpMethod.POST, new Request.Callback() {
            public void onCompleted(Response response) {
                /* handle the result */
                Log.d("uploadPhoto", "upload onComplete");
            }
        }).executeAsync();
    }

    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;
    private String mFileName;

    /** Create a File for saving an image or video */
    private File getOutputMediaFile(int type) {
        // To be safe, you should check that the SDCard is mounted

        if (Environment.getExternalStorageState() != null) {
            // this works for Android 2.2 and above
            File mediaStorageDir = new File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                    "AndroidCameraTestsFolder");

            // This location works best if you want the created images to be
            // shared
            // between applications and persist after your app has been
            // uninstalled.

            // Create the storage directory if it does not exist
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    return null;
                }
            }

            // Create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            File mediaFile;
            if (type == MEDIA_TYPE_IMAGE) {
                mFileName = "IMG_" + timeStamp + ".jpg";
                mediaFile = new File(mediaStorageDir.getPath() + File.separator + mFileName);
            } else if (type == MEDIA_TYPE_VIDEO) {
                mFileName = "VID_" + timeStamp + ".mp4";
                mediaFile = new File(mediaStorageDir.getPath() + File.separator + mFileName);
            } else {
                return null;
            }

            return mediaFile;
        }
        return null;
    }

    @Override
    public void onPause() {
        super.onPause();
        uiHelper.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
        blocParty = null;
    }

    /**
     * Notifies that the session token has been updated.
     */
    private void tokenUpdated() {
        Log.d(TAG, "tokenUpdated");
    }

    /*
     * Checks for session state changes and updates the Request if so. Methods
     * you want to execute only when authenticated in should be placed in here.
     */
    private void onSessionStateChange(final Session session, SessionState state, Exception exception) {
        if (session != null && session.isOpened()) { // Active session

            if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) { // Newly
                // updated
                // token
                Log.d(TAG, "tokenUpdated");
                tokenUpdated();
            } else { // Methods you call when in stable open session state go
                     // here.
                makeMeRequest(session);
                getFeedRequest(session);
            }
        } else {

            profilePictureView.setProfileId(null);
        }
    }

    private void getFeedRequest(final Session session) {
        Bundle params = new Bundle();
        /* make the API call */
        new Request(session, "/me/home", params, HttpMethod.GET, new Request.Callback() {
            public void onCompleted(Response response) {

                GraphObject graphObject = response.getGraphObject();

                if (graphObject != null) {
                    JSONObject jsonObject = graphObject.getInnerJSONObject();
                    try {
                        JSONArray array = jsonObject.getJSONArray("data");

                        for (int i = 0; i < array.length(); i++) {
                            JSONObject object = (JSONObject) array.get(i);
                            //Log.d("raw object is ", object.toString());
                            if (object.has("picture")) {
                                PhotoPost post = new PhotoPost();
                                String url = object.getString("picture");
                                //Log.d("picture ", url);
                                post.setImageUrl(url);
                                post.setId(object.getString("id"));
                                if (object.has("story")) {
                                    post.setStory(object.getString("story"));
                                }
                                photoArray.add(post);
                            }
                        }
                        Log.d("photoarray size is ", String.valueOf(photoArray.size()));
                        PhotoPostAdapter adapter = new PhotoPostAdapter(getActivity(), photoArray);
                        listView.setAdapter(adapter);

                        for (PhotoPost p : photoArray) {
                            p.loadImage(adapter);
                        }
                    } catch (JSONException e) {

                        e.printStackTrace();
                    }
                }

            }
        }).executeAsync();

    }

    private void makeMeRequest(final Session session) {
        Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
            @Override
            public void onCompleted(GraphUser user, Response response) { // retrieve
                // GraphUser
                if (session == Session.getActiveSession()) {
                    if (user != null) {
                        profilePictureView.setProfileId(user.getId());
                        titleText.setText(user.getName());
                        requestPublishPermissions(session);
                    }
                }
                if (response.getError() != null) {
                    handleError(response.getError());
                }
            }
        });
        request.executeAsync();
    }

    private static int CAMERA_TAKE_PHOTO_REQUEST_CODE = 100;

    public void startCamera() {

        // give the image a name so we can store it in the phone's default
        // location
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "IMG_" + timeStamp + ".jpg");

        File f = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        fileUri = Uri.fromFile(f);

        mCurrentPhotoPath = f.getAbsolutePath();
        Log.d("photo path is ", mCurrentPhotoPath.toString());
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra("return-data", true);

        getActivity().setResult(RESULT_OK, intent);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
        // start the image capture Intent
        startActivityForResult(intent, CAMERA_TAKE_PHOTO_REQUEST_CODE);
    }

    /**
     * Resets the view to the initial defaults.
     */
    private void init(Bundle savedInstanceState) {
        announceButton.setEnabled(false);
        messageButton.setEnabled(false);

        listElements = new ArrayList<BaseListElement>();

        /*
         * listElements.add(new EatListElement(0)); listElements.add(new
         * LocationListElement(1)); listElements.add(new PeopleListElement(2));
         * listElements.add(new PhotoListElement(3));
         */

        if (savedInstanceState != null) {
            for (BaseListElement listElement : listElements) {
                // listElement.restoreState(savedInstanceState);
            }
            pendingAnnounce = savedInstanceState.getBoolean(PENDING_ANNOUNCE_KEY, false);
        }

        Session session = Session.getActiveSession();
        if (session != null && session.isOpened()) {
            makeMeRequest(session);
        }
    }

    private void requestPublishPermissions(Session session) {
        Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(this, PERMISSION)
                // demonstrate how to set an audience for the publish
                // permissions,
                // if none are set, this defaults to FRIENDS
                .setDefaultAudience(SessionDefaultAudience.FRIENDS).setRequestCode(REAUTH_ACTIVITY_CODE);
        if (session == null) {
            session.requestNewPublishPermissions(newPermissionsRequest);
        }
    }

    private void showSuccessResponse(String postId) {
        String dialogBody;
        if (postId != null) {
            dialogBody = String.format(getString(R.string.result_dialog_text_with_id), postId);
        } else {
            dialogBody = getString(R.string.result_dialog_text_default);
        }
        showResultDialog(dialogBody);
    }

    private void showCancelResponse() {
        showResultDialog(getString(R.string.result_dialog_text_canceled));
    }

    private void showResultDialog(String dialogBody) {
        new AlertDialog.Builder(getActivity()).setPositiveButton(R.string.result_dialog_button_text, null)
                .setTitle(R.string.result_dialog_title).setMessage(dialogBody).show();
    }

    private void handleError(FacebookRequestError error) {
        DialogInterface.OnClickListener listener = null;
        String dialogBody = null;

        if (error == null) {
            dialogBody = getString(R.string.error_dialog_default_text);
        } else {
            switch (error.getCategory()) {
            case AUTHENTICATION_RETRY:
                // tell the user what happened by getting the message id, and
                // retry the operation later
                String userAction = (error.shouldNotifyUser()) ? "" : getString(error.getUserActionMessageId());
                dialogBody = getString(R.string.error_authentication_retry, userAction);
                listener = new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Intent intent = new Intent(Intent.ACTION_VIEW, M_FACEBOOK_URL);
                        startActivity(intent);
                    }
                };
                break;

            case AUTHENTICATION_REOPEN_SESSION:
                // close the session and reopen it.
                dialogBody = getString(R.string.error_authentication_reopen);
                listener = new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Session session = Session.getActiveSession();
                        if (session != null && !session.isClosed()) {
                            session.closeAndClearTokenInformation();
                        }
                    }
                };
                break;

            case PERMISSION:
                // request the publish permission
                dialogBody = getString(R.string.error_permission);
                listener = new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        pendingAnnounce = true;
                        requestPublishPermissions(Session.getActiveSession());
                    }
                };
                break;

            case SERVER:
            case THROTTLING:
                // this is usually temporary, don't clear the fields, and
                // ask the user to try again
                dialogBody = getString(R.string.error_server);
                break;

            case BAD_REQUEST:
                // this is likely a coding error, ask the user to file a bug
                dialogBody = getString(R.string.error_bad_request, error.getErrorMessage());
                break;

            case OTHER:
            case CLIENT:
            default:
                // an unknown issue occurred, this could be a code error, or
                // a server side issue, log the issue, and either ask the
                // user to retry, or file a bug
                dialogBody = getString(R.string.error_unknown, error.getErrorMessage());
                break;
            }
        }

        new AlertDialog.Builder(getActivity()).setPositiveButton(R.string.error_dialog_button_text, listener)
                .setTitle(R.string.error_dialog_title).setMessage(dialogBody).show();
    }

    /**
     * Used to inspect the response from posting an action
     */
    private interface PostResponse extends GraphObject {
        String getId();
    }

    @Override
    public void onRefresh() {
        // TODO Auto-generated method stub
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                swipeLayout.setRefreshing(false);
                onSessionStateChange(Session.getActiveSession(), SessionState.OPENING, null);
            }
        }, 5000);
    }

}