package com.mobmonkey.mobmonkeyandroid.fragments; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import org.json.JSONException; import org.json.JSONObject; import com.facebook.Request; import com.facebook.Response; import com.facebook.Session; import com.facebook.model.GraphUser; import com.mobmonkey.mobmonkeyandroid.R; import com.mobmonkey.mobmonkeyandroid.listeners.*; import com.mobmonkey.mobmonkeyandroid.utils.MMConstants; import com.mobmonkey.mobmonkeyandroid.utils.MMFragment; import com.mobmonkey.mobmonkeyandroid.utils.MMUtility; import com.mobmonkey.mobmonkeysdk.adapters.MMUserAdapter; import com.mobmonkey.mobmonkeysdk.utils.MMSDKConstants; import com.mobmonkey.mobmonkeysdk.utils.MMCallback; import com.mobmonkey.mobmonkeysdk.utils.MMProgressDialog; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnKeyListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.DatePicker; import android.widget.DatePicker.OnDateChangedListener; import android.widget.EditText; import android.widget.ScrollView; import android.widget.Toast; /** * Android {@link Fragment} screen displays the user's information. * @author Dezapp, LLC * */ public class MyInfoFragment extends MMFragment implements OnClickListener, OnKeyListener, OnTouchListener, OnDateChangedListener { private static final String TAG = "MyInfoFragment: "; private SharedPreferences userPrefs; private SharedPreferences.Editor userPrefsEditor; private GraphUser facebookUser; private InputMethodManager inputMethodManager; private Button btnSave; private EditText etFirstName; private EditText etLastName; private EditText etEmailAddress; private EditText etNewPassword; private EditText etConfirmPassword; private EditText etBirthdate; private EditText etGender; private Calendar birthdate; private JSONObject response; private String oAuthProvider; private String newPassword; /* * (non-Javadoc) * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { userPrefs = getActivity().getSharedPreferences(MMSDKConstants.USER_PREFS, Activity.MODE_PRIVATE); userPrefsEditor = userPrefs.edit(); oAuthProvider = userPrefs.getString(MMSDKConstants.KEY_OAUTH_PROVIDER, MMSDKConstants.DEFAULT_STRING_EMPTY); if(oAuthProvider.equals(MMSDKConstants.OAUTH_PROVIDER_FACEBOOK)) { Session session = Session.getActiveSession(); Session.NewPermissionsRequest request = new Session.NewPermissionsRequest(getActivity(), Arrays.asList(MMSDKConstants.FACEBOOK_REQ_PERM_EMAIL, MMSDKConstants.FACEBOOK_REQ_PERM_BIRTHDAY)); session.requestNewReadPermissions(request); Request.executeMeRequestAsync(session, new RequestGraphUserCallback()); } else { MMUserAdapter.getUserInfo(new UserInfoCallback()); MMProgressDialog.displayDialog(getActivity(), MMSDKConstants.DEFAULT_STRING_EMPTY, getString(R.string.pd_loading_user_info)); } inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); View view = inflater.inflate(R.layout.fragment_myinfo_screen, container, false); btnSave = (Button) view.findViewById(R.id.btnsave); ScrollView svMyInfo = (ScrollView) view.findViewById(R.id.svmyinfo); etFirstName = (EditText) view.findViewById(R.id.etfirstname); etLastName = (EditText) view.findViewById(R.id.etlastname); etEmailAddress = (EditText) view.findViewById(R.id.etemailaddress); etNewPassword = (EditText) view.findViewById(R.id.etnewpassword); etConfirmPassword = (EditText) view.findViewById(R.id.etconfirmpassword); etBirthdate = (EditText) view.findViewById(R.id.etbirthdate); etGender = (EditText) view.findViewById(R.id.etgender); birthdate = Calendar.getInstance(); btnSave.setOnClickListener(MyInfoFragment.this); svMyInfo.setOnTouchListener(MyInfoFragment.this); etEmailAddress.setFocusable(false); etEmailAddress.setFocusableInTouchMode(false); etEmailAddress.setClickable(false); Log.d(TAG, "User has login with " + userPrefs.getString(MMSDKConstants.KEY_OAUTH_PROVIDER, MMSDKConstants.DEFAULT_STRING_EMPTY) + " account."); // if user signed in with Facebook account, they can edit nothing in this screen. if(oAuthProvider.equals(MMSDKConstants.OAUTH_PROVIDER_FACEBOOK)) { btnSave.setVisibility(View.INVISIBLE); etFirstName.setFocusable(false); etFirstName.setClickable(false); etLastName.setFocusable(false); etLastName.setClickable(false); etEmailAddress.setFocusable(false); etEmailAddress.setClickable(false); etBirthdate.setFocusable(false); etBirthdate.setClickable(false); etBirthdate.setFocusable(false); etBirthdate.setClickable(false); etGender.setFocusable(false); etGender.setClickable(false); // make new password and confirm password disappear etNewPassword.setVisibility(View.GONE); etConfirmPassword.setVisibility(View.GONE); } // if user signed in with twitter account, they can edit every fields except email and password else if(oAuthProvider.equals(MMSDKConstants.OAUTH_PROVIDER_TWITTER)) { // disable email etEmailAddress.setFocusable(false); etEmailAddress.setClickable(false); // set Listener to birth date, and Gender fields etLastName.setOnKeyListener(MyInfoFragment.this); etBirthdate.setOnTouchListener(MyInfoFragment.this); etGender.setOnTouchListener(MyInfoFragment.this); // make new password and confirm password disappear etNewPassword.setVisibility(View.GONE); etConfirmPassword.setVisibility(View.GONE); } // if user signed in with mobmonkey account, they can edit all fields but the email. else { etEmailAddress.setFocusable(false); etEmailAddress.setClickable(false); etConfirmPassword.setOnKeyListener(MyInfoFragment.this); etBirthdate.setOnTouchListener(MyInfoFragment.this); etGender.setOnTouchListener(MyInfoFragment.this); } return view; } /* * (non-Javadoc) * @see android.support.v4.app.Fragment#onAttach(android.app.Activity) */ @Override public void onAttach(Activity activity) { super.onAttach(activity); if(activity instanceof MMOnFragmentFinishListener) { fragmentFinishListener = (MMOnFragmentFinishListener) activity; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d(TAG, TAG + "onActivityResult"); } /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View view) { switch(view.getId()) { case R.id.btnsave: saveUserInfo(); break; } } /** * {@link OnKeyListener} handle when user finished entering confirmed password and go to the birthdate {@link EditText}, removes the soft keyboard */ /* (non-Javadoc) * @see android.view.View.OnKeyListener#onKey(android.view.View, int, android.view.KeyEvent) */ @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if(event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { if(oAuthProvider.equals(MMSDKConstants.OAUTH_PROVIDER_TWITTER)) { inputMethodManager.hideSoftInputFromWindow(etLastName.getWindowToken(), 0); return true; } else { inputMethodManager.hideSoftInputFromWindow(etConfirmPassword.getWindowToken(), 0); return true; } } return false; } /** * {@link OnTouchListener} handler for birthdate and gender {@link EditText}. When the {@link EditText}s are touched, it will prompt the user to select his/her birthdate or gender. */ /* * (non-Javadoc) * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) */ @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_UP) { switch(v.getId()) { case R.id.etbirthdate: inputMethodManager.hideSoftInputFromWindow(etBirthdate.getWindowToken(), 0); promptUserBirthdate(); return true; case R.id.etgender: inputMethodManager.hideSoftInputFromWindow(etGender.getWindowToken(), 0); promptUserGender(); return true; } } return false; } /* * (non-Javadoc) * @see android.widget.DatePicker.OnDateChangedListener#onDateChanged(android.widget.DatePicker, int, int, int) */ @Override public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { } @Override public void onFragmentBackPressed() { fragmentFinishListener.onFragmentFinish(); } /** * Function that converts the gender of the user from {@link String} representation to {@link Integer} representation. * @return */ private int convertGender() { int gender = MMSDKConstants.DEFAULT_INT; if(etGender.getText().toString().equalsIgnoreCase(MMSDKConstants.TEXT_MALE)) { gender = MMSDKConstants.NUM_MALE; } else if(etGender.getText().toString().equalsIgnoreCase(MMSDKConstants.TEXT_FEMALE)) { gender = MMSDKConstants.NUM_FEMALE; } else { gender = (Integer) null; } return gender; } /** * Prompt the user with an {@link AlertDialog} to select his/her birthdate. */ private void promptUserBirthdate() { LayoutInflater layoutInflator = LayoutInflater.from(getActivity()); View vBirthdate = layoutInflator.inflate(R.layout.birthdate_picker, null); final DatePicker dpBirthdate = (DatePicker) vBirthdate.findViewById(R.id.dpbirthdate); if(birthdate == null) { birthdate = Calendar.getInstance(); birthdate.setTimeInMillis(System.currentTimeMillis()); birthdate.set(birthdate.get(Calendar.YEAR) - 21, birthdate.get(Calendar.MONTH), birthdate.get(Calendar.DAY_OF_MONTH)); } dpBirthdate.init(birthdate.get(Calendar.YEAR), birthdate.get(Calendar.MONTH), birthdate.get(Calendar.DAY_OF_MONTH), MyInfoFragment.this); new AlertDialog.Builder(getActivity()) .setTitle(R.string.ad_title_birthdate) .setView(vBirthdate) .setCancelable(false) .setPositiveButton(R.string.ad_btn_choose, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { birthdate.set(dpBirthdate.getYear(), dpBirthdate.getMonth(), dpBirthdate.getDayOfMonth()); etBirthdate.setText(MMUtility.getDate(birthdate.getTimeInMillis(), MMSDKConstants.DATE_FORMAT_MMM_DD_COMMA_YYYY)); } }) .setNegativeButton(R.string.ad_btn_cancel, null) .show(); } /** * Prompt the user with an {@link AlertDialog} for his/her gender. */ private void promptUserGender() { new AlertDialog.Builder(getActivity()) .setTitle(R.string.ad_title_gender) .setItems(R.array.ad_list_gender, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { etGender.setText(getResources().getStringArray(R.array.ad_list_gender)[which]); } }) .setNegativeButton(R.string.ad_btn_cancel, null) .setCancelable(false) .show(); } /** * */ public void setUserInfo() { try{ etFirstName.setText(response.getString(MMSDKConstants.KEY_FIRST_NAME)); etLastName.setText(response.getString(MMSDKConstants.KEY_LAST_NAME)); etEmailAddress.setText(response.getString(MMSDKConstants.KEY_EMAIL_ADDRESS)); birthdate.setTimeInMillis(response.getLong(MMSDKConstants.KEY_BIRTHDATE)); etBirthdate.setText(MMUtility.getDate(birthdate.getTimeInMillis(), MMSDKConstants.DATE_FORMAT_MMM_DD_COMMA_YYYY)); if(response.getInt(MMSDKConstants.KEY_GENDER) == MMSDKConstants.NUM_MALE) etGender.setText(MMSDKConstants.TEXT_MALE); else if(response.getInt(MMSDKConstants.KEY_GENDER) == MMSDKConstants.NUM_FEMALE) etGender.setText(MMSDKConstants.TEXT_FEMALE); } catch(Exception e) { e.printStackTrace(); } } /** * Function that check if the first name {@link EditText} field is valid and is not empty and stored the value into a {@link HashMap}. * @return <code>false</code> otherwise */ private boolean checkFields() { if(TextUtils.isEmpty(etFirstName.getText().toString())) { displayAlert(R.string.ad_message_first_name_empty); return false; } else { return checkLastName(); } } /** * Function that check if the last name {@link EditText} field is valid and is not empty and stored the value into a {@link HashMap}. * @return <code>false</code> otherwise */ private boolean checkLastName() { if(TextUtils.isEmpty(etLastName.getText().toString())) { displayAlert(R.string.ad_message_last_name_empty); return false; } else { return checkPassword(); } } /** * Function that check if the password {@link EditText} fields is empty, set the password to the oldPassword. Else check if the password fields are the same. * In addition, it compare the passwords to determine if they are equal and and stored the value into a {@link HashMap}. * @return <code>false</code> otherwise */ private boolean checkPassword() { if(TextUtils.isEmpty(newPassword)) { if(TextUtils.isEmpty(etConfirmPassword.getText())) { newPassword = userPrefs.getString(MMSDKConstants.KEY_AUTH, MMSDKConstants.DEFAULT_STRING_EMPTY); return checkBirthdate(); } else { displayAlert(R.string.ad_message_password_not_match); return false; } } else if(!newPassword.equals(etConfirmPassword.getText())){ displayAlert(R.string.ad_message_password_not_match); userPrefsEditor.putString(MMSDKConstants.KEY_PASSWORD, newPassword); userPrefsEditor.commit(); return false; } return true; } /** * Function that check if the birthdate {@link EditText} field is valid and is not empty and stored the value into a {@link HashMap}. * @return <code>false</code> otherwise */ private boolean checkBirthdate() { if(!TextUtils.isEmpty(etBirthdate.getText())) { return checkGender(); } else { displayAlert(R.string.ad_message_invalid_birthdate); return false; } } /** * Function that check if the gender {@link EditText} field is valid and is not empty and stored the value into a {@link HashMap}. * @return <code>false</code> otherwise */ private boolean checkGender() { if(!TextUtils.isEmpty(etGender.getText())) { return true; } else { displayAlert(R.string.ad_message_invalid_gender); return false; } } /** * */ private void saveUserInfo() { newPassword = etNewPassword.getText().toString(); if(checkFields()) { try { MMProgressDialog.displayDialog(getActivity(), MMSDKConstants.DEFAULT_STRING_EMPTY, getString(R.string.pd_updating_user_info)); MMUserAdapter.updateUserInfo(new UserInfoUpdateCallback(), etFirstName.getText().toString(), etLastName.getText().toString(), newPassword, birthdate.getTimeInMillis(), convertGender(), response.getString(MMSDKConstants.KEY_CITY), response.getString(MMSDKConstants.KEY_STATE), response.getString(MMSDKConstants.KEY_ZIP), response.getBoolean(MMSDKConstants.KEY_ACCEPTEDTOS)); } catch (JSONException e) { e.printStackTrace(); } } } /** * * @param messageId */ private void displayAlert(int messageId) { new AlertDialog.Builder(getActivity()) .setTitle(R.string.app_name) .setMessage(messageId) .setNeutralButton(android.R.string.ok, null) .show(); } /** * * @author Dezapp, LLC * */ private class UserInfoCallback implements MMCallback { @Override public void processCallback(Object obj) { MMProgressDialog.dismissDialog(); if(obj != null) { if(((String) obj).equals(MMSDKConstants.CONNECTION_TIMED_OUT)) { Toast.makeText(getActivity(), getString(R.string.toast_connection_timed_out), Toast.LENGTH_SHORT).show(); } else { try { response = new JSONObject((String) obj); setUserInfo(); } catch (JSONException e) { e.printStackTrace(); } } } } } /** * * @author Dezapp, LLC * */ private class UserInfoUpdateCallback implements MMCallback { @Override public void processCallback(Object obj) { MMProgressDialog.dismissDialog(); if(obj != null) { if(((String) obj).equals(MMSDKConstants.CONNECTION_TIMED_OUT)) { Toast.makeText(getActivity(), getString(R.string.toast_connection_timed_out), Toast.LENGTH_SHORT).show(); } else { try { JSONObject jObj = new JSONObject((String) obj); if(jObj.getString(MMSDKConstants.JSON_KEY_STATUS).equals(MMSDKConstants.RESPONSE_STATUS_SUCCESS)) { Toast.makeText(getActivity(), jObj.getString(MMSDKConstants.JSON_KEY_DESCRIPTION), Toast.LENGTH_SHORT).show(); fragmentFinishListener.onFragmentFinish(); } } catch (JSONException e) { e.printStackTrace(); } } } } } /** * Custom {@link Request.GraphUserCallback} specifically for {@link MyInfoFragment} to the completion of the {@link Request}.executeMeRequestAsync({@link Session}, {@link Request.GraphUserCallback}). * @author Dezapp, LLC * */ private class RequestGraphUserCallback implements Request.GraphUserCallback { @Override public void onCompleted(GraphUser user, Response response) { Log.d(TAG, TAG + "onCompleted"); if(user != null) { facebookUser = user; etFirstName.setText(facebookUser.getFirstName()); etLastName.setText(facebookUser.getLastName()); etEmailAddress.setText((String) facebookUser.getProperty(MMSDKConstants.FACEBOOK_REQ_PERM_EMAIL)); etBirthdate.setText(facebookUser.getBirthday()); etGender.setText((String) facebookUser.getProperty(MMSDKConstants.FACEBOOK_REQ_PERM_GENDER)); } } } }