Android Open Source - MySms Conversations Fragment






From Project

Back to project page MySms.

License

The source code is released under:

Apache License

If you think the Android project MySms listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.henningta.mysms;
//from  w  w  w. ja  v a2s. c o m
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.view.ActionMode;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;

public class ConversationsFragment extends Fragment implements AdapterView.OnItemClickListener,
    AdapterView.OnItemLongClickListener {

  public static final String TAG = "com.henningta.mysms.ConversationsFragment";

  private OnSourceSelected callback;

  private Activity activity;

  private ActionMode actionMode;

  private ListView lvConversations;
  private ConversationAdapter conversationAdapter;

  public static ConversationsFragment newInstance() {
    return new ConversationsFragment();
  }

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);

    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
      callback = (OnSourceSelected)activity;
    } catch (ClassCastException e) {
      throw new ClassCastException(activity.toString()
          + " must implement OnConversationSelected");
    }
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    actionMode = null;
    setRetainInstance(true);
    setHasOptionsMenu(true);
  }

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

    TextView tvNoConversations = (TextView)view.findViewById(R.id.tvNoConversations);

    lvConversations = (ListView)view.findViewById(R.id.lvConversations);
    lvConversations.setEmptyView(tvNoConversations);
    lvConversations.setOnItemClickListener(this);
    lvConversations.setOnItemLongClickListener(this);

    return view;
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    this.activity = getActivity();

    // set toolbar
    ((ActionBarActivity)activity).getSupportActionBar().setTitle(R.string.app_name);
    ((ActionBarActivity)activity).getSupportActionBar().setSubtitle(null);
  }

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

    // init db
    DatabaseHandler dbHandler = new DatabaseHandler(activity);

    // initialize adapter
    conversationAdapter = new ConversationAdapter(activity, R.layout.conversation_list_item,
        dbHandler.getConversationList());
    conversationAdapter.sort(new ConversationComparator());
    lvConversations.setAdapter(conversationAdapter);

    // close db
    dbHandler.close();

    // cancel notifications if any
    SmsTools.cancelNotifications(activity);
    activity.sendBroadcast(new Intent(activity, NotificationReceiver.class));

    activity.registerReceiver(conversationReceiver, new IntentFilter(Settings.ACTION_CONVERSATION));
  }

  @Override
  public void onPause() {
    super.onPause();
    activity.unregisterReceiver(conversationReceiver);
  }

  @Override
  public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Inflate the menu; this adds items to the action bar if it is present.
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.main, menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    // Handle presses on the action bar items
    switch (item.getItemId()) {
      case R.id.action_new:
        addConversation();
        return true;
      case R.id.action_settings:
        Intent settingsIntent = new Intent(activity, SettingsActivity.class);
        startActivity(settingsIntent);
        return true;
      default:
        return super.onOptionsItemSelected(item);
    }
  }

  // Container Activity must implement this interface
  public interface OnSourceSelected {
    public void onSourceSelected(String source);
  }

  @Override
  public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    if (actionMode != null) {
      // if action mode, toggle checked state of item
      conversationAdapter.toggleChecked(position);
      actionMode.invalidate();
    } else {
      // do item click
      Conversation conversation = (Conversation)parent.getItemAtPosition(position);
      callback.onSourceSelected(conversation.getSource());
    }
  }

  @Override
  public boolean onItemLongClick(AdapterView<?> parent, View v, final int position, long id) {
    if (actionMode != null) {
      return false;
    }

    final Conversation conversation = conversationAdapter.getItem(position);

    if (conversation.isContact()) {
      setChecked(position);
    } else {
      String[] items = new String[] { "Add contact", "Select" };

      AlertDialog.Builder builder = new AlertDialog.Builder(activity);
      builder.setTitle(conversation.getName())
          .setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
              switch (which) {
                case 0:
                  Intent intent = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT,
                      Uri.parse("tel:" + conversation.getSource()));
                  intent.putExtra(ContactsContract.Intents.EXTRA_FORCE_CREATE, true);
                  startActivityForResult(intent, Settings.REQUEST_ADD_CONTACT);
                  break;
                case 1:
                  setChecked(position);
                  break;
                default:
                  break;
              }
            }
          });
      AlertDialog dialog = builder.create();
      dialog.show();
    }

    return true;
  }

  /*private void loadPreferences() {
    Settings.NOTIFICATIONS_ENABLED = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("notifications_new_message", true);
    Settings.NOTIFICATIONS_VIBRATE = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("notifications_new_message_vibrate", true);
  }*/

  private void setChecked(int position) {
    // set checked selected item and enter multi selection mode
    conversationAdapter.setChecked(position, true);
    ((ActionBarActivity)activity).startSupportActionMode(new ActionModeCallback(activity));
    actionMode.invalidate();
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (resultCode) {
      case Activity.RESULT_CANCELED:
        Log.d(this.getClass().getName(), "Activity cancelled");
        return;
      case Activity.RESULT_OK:
        switch (requestCode) {
          case Settings.REQUEST_CONTACT:
            // retrieve contact data
            Uri contactData = data.getData();

            // initialize cursor
            Cursor c = initializeCursor(activity, contactData);

            if (c != null && c.moveToFirst()) {
              ArrayList<String> nums, options;

              // get display name
              String name = c.getString(c.getColumnIndex(
                  ContactsContract.Contacts.DISPLAY_NAME));
              Log.d(this.getClass().getName(), "Selected " + name);

              // check for phone numbers
              int hasPhoneNumber = Integer.parseInt(c.getString(c.getColumnIndex(
                  ContactsContract.Contacts.HAS_PHONE_NUMBER)));

              if (hasPhoneNumber == 0) {
                return;
              } else {
                // iterate through phone numbers
                String id = c.getString(c.getColumnIndex(BaseColumns._ID));
                Cursor pCur = activity.getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                    new String[] { id }, null);

                if (pCur == null) {
                  Toast.makeText(activity, "An unexpected error has occurred.",
                      Toast.LENGTH_SHORT).show();
                  return;
                }

                options = new ArrayList<>();
                nums = new ArrayList<>();
                while (pCur.moveToNext()) {
                  // add phone numbers to options
                  int type = pCur.getInt(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                  int typeRes = ContactsContract.CommonDataKinds.Phone.getTypeLabelResource(type);
                  String typeStr = this.getString(typeRes);

                  // set phone label
                  if (type == ContactsContract.CommonDataKinds.BaseTypes.TYPE_CUSTOM) {
                    typeStr = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LABEL));

                    if (typeStr == null || typeStr.equals("")) {
                      typeStr = "Custom";
                    }
                  }

                  String number = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                      .replaceAll("[^0-9]", "");
                  String formattedNumber = Settings.formatSource(number);

                  if (typeStr == null || typeStr.equals("")) {
                    options.add("Other: " + formattedNumber);
                  } else {
                    options.add(typeStr + ": " + formattedNumber);
                  }

                  nums.add(number);
                }
                pCur.close();
              }
              c.close();

              showPhoneNumberDialog(name, options, nums);
            }
            break;
          case Settings.REQUEST_ADD_CONTACT:
            activity.sendBroadcast(new Intent(Settings.ACTION_CONVERSATION));
            break;
        }
        break;
      default:
        break;
    }
  }

  private Cursor initializeCursor(Context context, Uri contactData) {
    CursorLoader cl = new CursorLoader(context, contactData, null, null, null, null);
    return cl.loadInBackground();
  }

  private void showPhoneNumberDialog(final String name, final ArrayList<String> options,
                     final ArrayList<String> nums) {
    final CharSequence[] items = options.toArray(new String[options.size()]);

    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setTitle(name)
        .setItems(items, new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            String source = nums.get(which);
            callback.onSourceSelected(source);
          }
        });
    AlertDialog dialog = builder.create();
    dialog.show();
  }

  private void addConversation() {
    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
    startActivityForResult(intent, Settings.REQUEST_CONTACT);
  }

  /**
   * Compares conversations by time of last update
   */
  class ConversationComparator implements Comparator<Conversation> {
    @Override
    public int compare(Conversation c1, Conversation c2) {
      return c1.getTime() < c2.getTime() ? 1 : c1.getTime() == c2.getTime() ? 0 : -1;
    }
  }

  /**
   * Broadcast receiver to update UI
   */
  private BroadcastReceiver conversationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      DatabaseHandler dbHandler = new DatabaseHandler(context);
      // update adapter
      conversationAdapter.clear();
      conversationAdapter.addAll(dbHandler.getConversationList());
      conversationAdapter.sort(new ConversationComparator());
      dbHandler.close();
    }
  };

  private final class ActionModeCallback implements ActionMode.Callback {

    private Context context;

    public ActionModeCallback(Context context) {
      this.context = context;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
      conversationAdapter.enterMultiMode();

      // save global action mode
      actionMode = mode;
      return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
      // remove previous items
      menu.clear();
      final int checked = conversationAdapter.getCheckedItemCount();

      // update title with number of checked items
      mode.setTitle(checked + " selected");
      switch (checked) {
        case 0:
          // if nothing checked - exit action mode
          mode.finish();
          return true;
        default:
          // inflate selection menu
          activity.getMenuInflater().inflate(R.menu.conversations_selected, menu);
          return true;
      }
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
      switch (item.getItemId()) {
        case R.id.action_discard:
          int count = conversationAdapter.getCheckedItemCount();
          String message = "Delete " + count;

          if (count == 1) {
            message += " conversation?";
          } else {
            message += " conversations?";
          }

          // initialize list of checked items and iterator starting at the end
          final LinkedList<Conversation> checkedList =
              new LinkedList<>(conversationAdapter.getCheckedItems());

          AlertDialog.Builder builder = new AlertDialog.Builder(context);
          builder.setTitle("Delete")
              .setMessage(message)
              .setPositiveButton("Delete", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                  deleteSelectedConversations(context, checkedList);
                }
              })
              .setNegativeButton("Cancel", null);
          AlertDialog dialog = builder.create();
          dialog.show();

          if (actionMode != null) {
            actionMode.finish();
          }

          return true;
        default:
          return false;
      }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
      conversationAdapter.exitMultiMode();
      actionMode = null;
    }

    private void deleteSelectedConversations(Context context, LinkedList<Conversation> checkedList) {
      DatabaseHandler dbHandler = new DatabaseHandler(context);

      // iterate through selected items and delete them
      for (Conversation conversation : checkedList) {
        dbHandler.deleteConversation(conversation.getSource());
        dbHandler.deleteMessages(conversation.getSource());
        conversationAdapter.remove(conversation);
      }

      dbHandler.close();
    }

  }

}




Java Source Code List

com.henningta.mysms.ConversationAdapter.java
com.henningta.mysms.Conversation.java
com.henningta.mysms.ConversationsFragment.java
com.henningta.mysms.DatabaseHandler.java
com.henningta.mysms.MainActivity.java
com.henningta.mysms.MessageAdapter.java
com.henningta.mysms.Message.java
com.henningta.mysms.MessagesFragment.java
com.henningta.mysms.NotificationReceiver.java
com.henningta.mysms.SettingsActivity.java
com.henningta.mysms.Settings.java
com.henningta.mysms.SmsDeliveredReceiver.java
com.henningta.mysms.SmsReceiver.java
com.henningta.mysms.SmsSentReceiver.java
com.henningta.mysms.SmsTools.java
com.henningta.mysms.WakeLocker.java