/** * Copyright 2010 Mark Wyszomierski */ package com.joelapenna.foursquared; import com.joelapenna.foursquare.Foursquare; import com.joelapenna.foursquare.types.Tip; import com.joelapenna.foursquare.types.User; import com.joelapenna.foursquare.types.Venue; import com.joelapenna.foursquared.util.RemoteResourceManager; import com.joelapenna.foursquared.util.StringFormatters; import com.joelapenna.foursquared.widget.TipActivityAdapter; import android.app.Activity; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; import java.io.IOException; import java.util.Observable; import java.util.Observer; /** * Shows actions available for a tip: * * <ul> * <li>Add to my to-do list</li> * <li>I've done this!</li> * </ul> * * The foursquare API doesn't tell us whether we've already marked a tip as * to-do or already done, so we just keep presenting the same options to the * user every time they look at this screen. * * @date March 24, 2010 * @author Mark Wyszomierski (markww@gmail.com) * */ public class TipActivity extends Activity { private static final String TAG = "TipActivity"; private static final boolean DEBUG = FoursquaredSettings.DEBUG; public static final String EXTRA_TIP_PARCEL = Foursquared.PACKAGE_NAME + ".TipActivity.EXTRA_TIP_PARCEL"; public static final String EXTRA_VENUE_NAME = Foursquared.PACKAGE_NAME + ".TipActivity.EXTRA_VENUE_NAME"; public static final int RESULT_TIP_MARKED_TODO = -2; public static final int RESULT_TIP_MARKED_DONE = -3; private TipActivityAdapter mListAdapter; private StateHolder mStateHolder; private ListView mListView; private Handler mHandler; private RemoteResourceManager mRrm; private RemoteResourceManagerObserver mResourcesObserver; private ProgressDialog mDlgProgress; private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) Log.d(TAG, "onReceive: " + intent); finish(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tip_activity); registerReceiver(mLoggedOutReceiver, new IntentFilter(Foursquared.INTENT_ACTION_LOGGED_OUT)); mRrm = ((Foursquared) getApplication()).getRemoteResourceManager(); mHandler = new Handler(); Object retained = getLastNonConfigurationInstance(); if (retained != null && retained instanceof StateHolder) { mStateHolder = (StateHolder) retained; mStateHolder.setActivityForTipTask(this); } else { mStateHolder = new StateHolder(); if (getIntent().getExtras() != null && getIntent().getExtras().containsKey(EXTRA_TIP_PARCEL)) { Tip tip = getIntent().getExtras().getParcelable(EXTRA_TIP_PARCEL); mStateHolder.setTip(tip); if (getIntent().getExtras().containsKey(EXTRA_VENUE_NAME)) { if (mStateHolder.getTip().getVenue() == null) { mStateHolder.getTip().setVenue(new Venue()); } mStateHolder.getTip().getVenue().setName( getIntent().getExtras().getString(EXTRA_VENUE_NAME)); } } else { Log.e(TAG, "TipActivity requires a tip pareclable in its intent extras."); finish(); return; } } ensureUi(); } @Override public void onResume() { super.onResume(); if (mStateHolder.getIsRunningTipTask()) { startProgressBar(mStateHolder.getTask()); } } @Override public void onPause() { super.onPause(); if (mResourcesObserver != null) { mRrm.deleteObserver(mResourcesObserver); } if (isFinishing()) { unregisterReceiver(mLoggedOutReceiver); mHandler.removeCallbacks(mRunnableUpdateUserPhoto); stopProgressBar(); } } @Override public Object onRetainNonConfigurationInstance() { mStateHolder.setActivityForTipTask(null); return mStateHolder; } private void ensureUi() { LinearLayout llHeader = (LinearLayout)findViewById(R.id.tipActivityHeaderView); llHeader.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showUserDetailsActivity(mStateHolder.getTip().getUser().getId()); } }); TextView tvTitle = (TextView)findViewById(R.id.tipActivityName); tvTitle.setText( getResources().getString(R.string.tip_activity_by) + " " + StringFormatters.getUserFullName(mStateHolder.getTip().getUser())); setUserPhoto(true); mListAdapter = new TipActivityAdapter( this, mStateHolder.getTip().getVenue() != null ? mStateHolder.getTip().getVenue().getName() : "", mStateHolder.getTip().getText()); mListView = (ListView)findViewById(R.id.tipActivityListView); mListView.setAdapter(mListAdapter); mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { switch (position) { case TipActivityAdapter.ACTION_ID_ADD_TODO_LIST: mStateHolder.startTipTask(TipActivity.this, mStateHolder.getTip().getId(), TipActivityAdapter.ACTION_ID_ADD_TODO_LIST); break; case TipActivityAdapter.ACTION_ID_IVE_DONE_THIS: mStateHolder.startTipTask(TipActivity.this, mStateHolder.getTip().getId(), TipActivityAdapter.ACTION_ID_IVE_DONE_THIS); break; } } }); } private void setUserPhoto(boolean fetchIfMissing) { ImageView iv = (ImageView)findViewById(R.id.tipActivityPhoto); User user = mStateHolder.getTip().getUser(); if (user != null) { try { Bitmap bitmap = BitmapFactory.decodeStream(mRrm.getInputStream(Uri.parse(user .getPhoto()))); iv.setImageBitmap(bitmap); } catch (IOException e) { setUserPhotoNone(user); // Try to fetch the photo. mResourcesObserver = new RemoteResourceManagerObserver(); mRrm.addObserver(mResourcesObserver); mRrm.request(Uri.parse(user.getPhoto())); } } } private void setUserPhotoNone(User user) { ImageView iv = (ImageView)findViewById(R.id.tipActivityPhoto); if (Foursquare.MALE.equals(user.getGender())) { iv.setImageResource(R.drawable.blank_boy); } else { iv.setImageResource(R.drawable.blank_girl); } } private void showUserDetailsActivity(String userId) { Intent intent = new Intent(this, UserDetailsActivity.class); intent.putExtra(UserDetailsActivity.EXTRA_USER_ID, userId); intent.putExtra(UserDetailsActivity.EXTRA_SHOW_ADD_FRIEND_OPTIONS, true); startActivity(intent); } private void startProgressBar(int task) { if (mDlgProgress == null) { String message = ""; switch (task) { case TipActivityAdapter.ACTION_ID_ADD_TODO_LIST: message = getResources().getString( R.string.tip_activity_action_todo); break; case TipActivityAdapter.ACTION_ID_IVE_DONE_THIS: message = getResources().getString( R.string.tip_activity_action_done_this); break; } mDlgProgress = ProgressDialog.show( this, getResources().getString(R.string.tip_activity_prgoress_title), message); } mDlgProgress.show(); } private void stopProgressBar() { if (mDlgProgress != null) { mDlgProgress.dismiss(); mDlgProgress = null; } } private void onTipTaskComplete(Tip tip, int type, Exception ex) { stopProgressBar(); mStateHolder.setIsRunningTipTask(false); if (tip != null) { String message = ""; switch (type) { case TipActivityAdapter.ACTION_ID_ADD_TODO_LIST: message = getResources().getString( R.string.tip_activity_prgoress_complete_todo); setResult(RESULT_TIP_MARKED_TODO); break; case TipActivityAdapter.ACTION_ID_IVE_DONE_THIS: message = getResources().getString( R.string.tip_activity_prgoress_complete_done); setResult(RESULT_TIP_MARKED_DONE); break; } Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } } private static class TipTask extends AsyncTask<String, Void, Tip> { private TipActivity mActivity; private String mTipId; private int mTask; private Exception mReason; public TipTask(TipActivity activity, String tipid, int task) { mActivity = activity; mTipId = tipid; mTask = task; } public void setActivity(TipActivity activity) { mActivity = activity; } @Override protected void onPreExecute() { mActivity.startProgressBar(mTask); } public int getTask() { return mTask; } @Override protected Tip doInBackground(String... params) { try { Foursquared foursquared = (Foursquared) mActivity.getApplication(); Foursquare foursquare = foursquared.getFoursquare(); Tip tip = null; switch (mTask) { case TipActivityAdapter.ACTION_ID_ADD_TODO_LIST: tip = foursquare.tipMarkTodo(mTipId); break; case TipActivityAdapter.ACTION_ID_IVE_DONE_THIS: tip = foursquare.tipMarkDone(mTipId); break; } return tip; } catch (Exception e) { if (DEBUG) Log.d(TAG, "TipTask: Exception performing tip task.", e); mReason = e; } return null; } @Override protected void onPostExecute(Tip tip) { if (DEBUG) Log.d(TAG, "TipTask: onPostExecute()"); if (mActivity != null) { mActivity.onTipTaskComplete(tip, mTask, mReason); } } @Override protected void onCancelled() { if (mActivity != null) { mActivity.onTipTaskComplete(null, mTask, new Exception("Tip task cancelled.")); } } } private static class StateHolder { private Tip mTip; private TipTask mTipTask; private boolean mIsRunningTipTask; public StateHolder() { mIsRunningTipTask = false; } public void setTip(Tip tip) { mTip = tip; } public Tip getTip() { return mTip; } public int getTask() { return mTipTask.getTask(); } public void startTipTask(TipActivity activity, String tipId, int task) { mIsRunningTipTask = true; mTipTask = new TipTask(activity, tipId, task); mTipTask.execute(); } public void setActivityForTipTask(TipActivity activity) { if (mTipTask != null) { mTipTask.setActivity(activity); } } public void setIsRunningTipTask(boolean isRunningTipTask) { mIsRunningTipTask = isRunningTipTask; } public boolean getIsRunningTipTask() { return mIsRunningTipTask; } } private class RemoteResourceManagerObserver implements Observer { @Override public void update(Observable observable, Object data) { mHandler.post(mRunnableUpdateUserPhoto); } } private Runnable mRunnableUpdateUserPhoto = new Runnable() { @Override public void run() { setUserPhoto(false); } }; }