Java tutorial
/** * 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); } }