Java tutorial
/* * Copyright (C) 2014 barter.li * * 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 li.barter.fragments; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.ListView; import com.android.volley.Request.Method; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; import li.barter.R; import li.barter.activities.AbstractBarterLiActivity.AlertStyle; import li.barter.adapters.ChatsAdapter; import li.barter.analytics.AnalyticsConstants.Screens; import li.barter.chat.ChatService; import li.barter.chat.ChatService.ChatServiceBinder; import li.barter.data.DBInterface; import li.barter.data.DBInterface.AsyncDbQueryCallback; import li.barter.data.DatabaseColumns; import li.barter.data.SQLConstants; import li.barter.data.SQLiteLoader; import li.barter.data.TableChatMessages; import li.barter.data.TableChats; import li.barter.data.ViewChatsWithMessagesAndUsers; import li.barter.fragments.dialogs.SingleChoiceDialogFragment; import li.barter.http.BlRequest; import li.barter.http.HttpConstants; import li.barter.http.HttpConstants.ApiEndpoints; import li.barter.http.HttpConstants.RequestId; import li.barter.http.IBlRequestContract; import li.barter.http.ResponseInfo; import li.barter.utils.AppConstants; import li.barter.utils.AppConstants.FragmentTags; import li.barter.utils.AppConstants.Keys; import li.barter.utils.AppConstants.Loaders; import li.barter.utils.AppConstants.QueryTokens; import li.barter.utils.Logger; import li.barter.utils.Utils; /** * Activity for displaying all the ongoing chats * * @author Vinay S Shenoy */ @FragmentTransition(enterAnimation = R.anim.slide_in_from_right, exitAnimation = R.anim.zoom_out, popEnterAnimation = R.anim.zoom_in, popExitAnimation = R.anim.slide_out_to_right) public class ChatsFragment extends AbstractBarterLiFragment implements LoaderCallbacks<Cursor>, OnItemClickListener, OnItemLongClickListener, ServiceConnection, AsyncDbQueryCallback { private static final String TAG = "ChatsFragment"; private ChatsAdapter mChatsAdapter; private ListView mChatsListView; private ChatService mChatService; private boolean mBoundToChatService; private String mDeleteChatId, mBlockUserId; private final String mChatSelectionForDelete = DatabaseColumns.CHAT_ID + SQLConstants.EQUALS_ARG; /** * Whether a chat message should be loaded immediately on opening */ private boolean mShouldLoadChat; /** * Id of the user to load immediately on opening */ private String mUserIdToLoad; /** * Chat message to prefill in the text box if chat is loaded directly */ private String mPreloadedChatMessage; /** * Reference to the Dialog Fragment for selecting the chat options */ private SingleChoiceDialogFragment mChatDialogFragment; private final Handler mHandler = new Handler(); @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { init(container, savedInstanceState); setHasOptionsMenu(true); setActionBarTitle(R.string.chat_fragment_title); final View view = inflater.inflate(R.layout.fragment_chats, container, false); mChatsListView = (ListView) view.findViewById(R.id.list_chats); mChatsAdapter = new ChatsAdapter(getActivity(), null); mChatsListView.setAdapter(mChatsAdapter); mChatsListView.setOnItemClickListener(this); mChatsListView.setOnItemLongClickListener(this); mChatDialogFragment = (SingleChoiceDialogFragment) getFragmentManager() .findFragmentByTag(FragmentTags.DIALOG_CHAT_LONGCLICK); if (savedInstanceState == null) { final Bundle args = getArguments(); if (args != null) { mShouldLoadChat = args.getBoolean(Keys.LOAD_CHAT); if (mShouldLoadChat) { mUserIdToLoad = args.getString(Keys.USER_ID); mPreloadedChatMessage = args.getString(Keys.CHAT_MESSAGE); } if (TextUtils.isEmpty(mUserIdToLoad)) { mShouldLoadChat = false; mPreloadedChatMessage = null; } } } getLoaderManager().restartLoader(Loaders.ALL_CHATS, null, this); return view; } @Override public void onPause() { super.onPause(); if (mBoundToChatService) { mChatService.setChatScreenVisible(true); getActivity().unbindService(this); } } @Override public void onResume() { super.onResume(); //Bind to chat service final Intent chatServiceBindIntent = new Intent(getActivity(), ChatService.class); getActivity().bindService(chatServiceBindIntent, this, Context.BIND_AUTO_CREATE); } ; @Override public void onDetach() { super.onDetach(); } @Override protected Object getTaskTag() { return hashCode(); } @Override public void onSuccess(final int requestId, final IBlRequestContract request, final ResponseInfo response) { if (requestId == RequestId.BLOCK_CHATS) { showCrouton(R.string.success_message_for_chatblock, AlertStyle.INFO); } } @Override public void onBadRequestError(final int requestId, final IBlRequestContract request, final int errorCode, final String errorMessage, final Bundle errorResponseBundle) { } @Override public Loader<Cursor> onCreateLoader(final int id, final Bundle args) { if (id == Loaders.ALL_CHATS) { return new SQLiteLoader(getActivity(), false, ViewChatsWithMessagesAndUsers.NAME, null, null, null, null, null, DatabaseColumns.TIMESTAMP_EPOCH + SQLConstants.DESCENDING, null); } return null; } @Override public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) { if (loader.getId() == Loaders.ALL_CHATS) { if (mShouldLoadChat) { if (isAttached()) { mHandler.post(new Runnable() { @Override public void run() { loadChat(mUserIdToLoad, mPreloadedChatMessage); //We only need to load on very launch of activity mShouldLoadChat = false; mPreloadedChatMessage = null; } }); } } else { mChatsAdapter.swapCursor(cursor); } } } @Override public void onLoaderReset(final Loader<Cursor> loader) { if (loader.getId() == Loaders.ALL_CHATS) { mChatsAdapter.swapCursor(null); } } @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { if (parent.getId() == R.id.list_chats) { final Cursor cursor = (Cursor) mChatsAdapter.getItem(position); loadChat(cursor.getString(cursor.getColumnIndex(DatabaseColumns.USER_ID)), cursor.getString(cursor.getColumnIndex(DatabaseColumns.CHAT_ID)), true, null); } } /** * Loads a chat directly. This is used in the case where the user directly taps on a chat button * on another user's profile page */ private void loadChat(String userId, String prefilledChatMessage) { //TODO: Vinay - Set the actual chat item highlighted final String chatId = Utils.generateChatId(userId, AppConstants.UserInfo.INSTANCE.getId()); loadChat(userId, chatId, false, prefilledChatMessage); } /** * Loads the actual chat screen. This is used in the case where the user taps on an item in the * list of chats * * @param userId The user Id of the chat to load * @param chatId The ID of the chat * @param fromClick Whether the chat was loaded as a result of a click on the list. Will be used * to decide whether to animate the detail fragment in * @param prefilledChatMessage Any message to prefill when loading it in */ private void loadChat(String userId, String chatId, boolean fromClick, String prefilledChatMessage) { final Bundle args = new Bundle(4); args.putString(Keys.USER_ID, userId); args.putString(Keys.CHAT_ID, chatId); args.putString(Keys.CHAT_MESSAGE, prefilledChatMessage); /*If Loaded directly, ensure that pressing back will finish the Activity*/ if (mShouldLoadChat) { args.putBoolean(Keys.FINISH_ON_BACK, true); } ChatDetailsFragment chatDetailsFragment = (ChatDetailsFragment) getFragmentManager() .findFragmentByTag(FragmentTags.CHAT_DETAILS); /*Chat details fragment will not be null in case of a multi-pane layout. * Makes no sense to instantiate a new fragment. Instead we just update * the one that's already visible*/ if (chatDetailsFragment != null && chatDetailsFragment.isResumed()) { chatDetailsFragment.updateUserInfo(args); } else { loadFragment(R.id.frame_content, (AbstractBarterLiFragment) Fragment.instantiate(getActivity(), ChatDetailsFragment.class.getName(), args), FragmentTags.CHAT_DETAILS, true, null, fromClick); } } @Override public void onServiceConnected(final ComponentName name, final IBinder service) { mBoundToChatService = true; mChatService = ((ChatServiceBinder) service).getService(); mChatService.clearChatNotifications(); mChatService.setChatScreenVisible(false); } @Override public void onServiceDisconnected(final ComponentName name) { mBoundToChatService = false; } @Override protected String getAnalyticsScreenName() { return Screens.CHATS; } @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mChatsAdapter.getItem(position); mDeleteChatId = cursor.getString(cursor.getColumnIndex(DatabaseColumns.CHAT_ID)); mBlockUserId = cursor.getString(cursor.getColumnIndex(DatabaseColumns.USER_ID)); showChatOptions(); return true; } /** * Show dialog for adding books */ private void showChatOptions() { mChatDialogFragment = new SingleChoiceDialogFragment(); mChatDialogFragment.show(AlertDialog.THEME_HOLO_LIGHT, R.array.chat_longclick_choices, 0, R.string.chat_longclick_dialog_head, getFragmentManager(), true, FragmentTags.DIALOG_CHAT_LONGCLICK); } @Override public boolean willHandleDialog(final DialogInterface dialog) { if ((mChatDialogFragment != null) && mChatDialogFragment.getDialog().equals(dialog)) { return true; } return super.willHandleDialog(dialog); } @Override public void onDialogClick(final DialogInterface dialog, final int which) { if ((mChatDialogFragment != null) && mChatDialogFragment.getDialog().equals(dialog)) { if (which == 0) { final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); // set title alertDialogBuilder.setTitle("Confirm"); // set dialog message alertDialogBuilder.setMessage(getResources().getString(R.string.delete_chat_alert_message)) .setCancelable(false).setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int id) { deleteChat(mDeleteChatId); dialog.dismiss(); } }).setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int id) { // if this button is clicked, just close // the dialog box and do nothing dialog.cancel(); } }); // create alert dialog final AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } else if (which == 1) { final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); // set title alertDialogBuilder.setTitle("Confirm"); // set dialog message alertDialogBuilder.setMessage(getResources().getString(R.string.block_user_alert_message)) .setCancelable(false).setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int id) { blockUser(mBlockUserId); dialog.dismiss(); } }).setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int id) { // if this button is clicked, just close // the dialog box and do nothing dialog.cancel(); } }); // create alert dialog final AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } } else { super.onDialogClick(dialog, which); } } private void deleteChat(String chatId) { DBInterface.deleteAsync(QueryTokens.DELETE_CHATS, getTaskTag(), null, TableChats.NAME, mChatSelectionForDelete, new String[] { chatId }, true, this); DBInterface.deleteAsync(QueryTokens.DELETE_CHAT_MESSAGES, getTaskTag(), null, TableChatMessages.NAME, mChatSelectionForDelete, new String[] { chatId }, true, this); } /** * Method to block user on the server using the userId * * @param userId representing the user selected */ private void blockUser(final String userId) { final JSONObject requestObject = new JSONObject(); try { requestObject.put(HttpConstants.USER_ID, userId); final BlRequest request = new BlRequest(Method.POST, HttpConstants.getApiBaseUrl() + ApiEndpoints.CHAT_BLOCK, requestObject.toString(), mVolleyCallbacks); request.setRequestId(RequestId.BLOCK_CHATS); final Map<String, String> params = new HashMap<String, String>(1); params.put(HttpConstants.USER_ID, userId); Logger.d(TAG, userId); request.setParams(params); addRequestToQueue(request, true, R.string.error_block_user, true); } catch (JSONException e) { Logger.e(TAG, e, "Error building create user json"); } } @Override public void onInsertComplete(int token, Object cookie, long insertRowId) { // TODO Auto-generated method stub } @Override public void onDeleteComplete(int token, Object cookie, int deleteCount) { switch (token) { case QueryTokens.DELETE_CHAT_MESSAGES: //add after delete features break; case QueryTokens.DELETE_CHATS: //add after delete features break; default: break; } } @Override public void onUpdateComplete(int token, Object cookie, int updateCount) { // TODO Auto-generated method stub } @Override public void onQueryComplete(int token, Object cookie, Cursor cursor) { // TODO Auto-generated method stub } }