com.sir_m2x.messenger.activities.ChatWindowFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.sir_m2x.messenger.activities.ChatWindowFragment.java

Source

/*
 * M2X Messenger, an implementation of the Yahoo Instant Messaging Client based on OpenYMSG for Android.
 * Copyright (C) 2011-2012  Mehran Maghoumi [aka SirM2X], maghoumi@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
    
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.sir_m2x.messenger.activities;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;

import org.openymsg.network.SessionState;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.TextKeyListener;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;

import com.sir_m2x.messenger.R;
import com.sir_m2x.messenger.classes.ChatWindowAdapter;
import com.sir_m2x.messenger.classes.IM;
import com.sir_m2x.messenger.services.MessengerService;
import com.sir_m2x.messenger.utils.Utils;

/**
 * @author Mehran Maghoumi [aka SirM2X] (maghoumi@gmail.com)
 * 
 */
public class ChatWindowFragment extends Fragment {
    public String friendId;
    private ListView lv;
    private EditText txtMessage = null;
    private boolean isTypingSelf = false;
    private NotificationCanceler notificationCanceler = null;
    public ChatFragmentListener imListener = new ChatFragmentListener();
    public ChatWindowAdapter listAdapter;

    public static ChatWindowFragment newInstance(final String friendId) {
        ChatWindowFragment chatWindowFragment = new ChatWindowFragment();
        Bundle bundle = new Bundle();
        bundle.putString("friendId", friendId);
        chatWindowFragment.setArguments(bundle);
        return chatWindowFragment;
    }

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.friendId = getArguments().getString("friendId");
        this.listAdapter = new ChatWindowAdapter(getActivity(), this.friendId);
    }

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

        this.notificationCanceler = new NotificationCanceler();
        this.notificationCanceler.start();
        this.friendId = getArguments().getString("friendId");

        Button btnSend = (Button) v.findViewById(R.id.btnSend);
        btnSend.setOnClickListener(this.btnSend_Click);

        this.lv = (ListView) v.findViewById(R.id.listView1);

        this.txtMessage = (EditText) v.findViewById(R.id.txtMessage);

        this.txtMessage.setOnEditorActionListener(this.txtMessage_EditorActionListener);
        this.txtMessage.addTextChangedListener(this.txtMessage_TextChangedListener);
        this.listAdapter.notifyDataSetChanged();
        return v;
    }

    @Override
    public void onResume() {
        this.listAdapter.notifyDataSetChanged();
        this.lv.setAdapter(this.listAdapter);

        getActivity().registerReceiver(this.imListener, new IntentFilter(MessengerService.INTENT_NEW_IM));
        getActivity().registerReceiver(this.imListener, new IntentFilter(MessengerService.INTENT_INSERT_SMILEY));
        getActivity().registerReceiver(this.imListener, new IntentFilter(MessengerService.INTENT_LIST_CHANGED));
        getActivity().registerReceiver(this.imListener, new IntentFilter(MessengerService.INTENT_BUZZ));
        super.onResume();
    };

    @Override
    public void onPause() {
        getActivity().unregisterReceiver(this.imListener);
        super.onPause();
    };

    /*
     * Handle "enter" on the TextView
     */
    OnEditorActionListener txtMessage_EditorActionListener = new OnEditorActionListener() {

        @Override
        public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) {
            sendIM();
            return true;
        }
    };
    /*
     * Handle sending typing notifications to the other party
     */
    TextWatcher txtMessage_TextChangedListener = new TextWatcher() {

        @Override
        public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
            if (ChatWindowFragment.this.isTypingSelf
                    || ChatWindowFragment.this.txtMessage.getText().toString().equals("")) {
                ChatWindowFragment.this.notificationCanceler.reschedule = true; // Reschedule
                // canceling typing
                // notification
                return;
            }
            try {
                ChatWindowFragment.this.isTypingSelf = true;
                MessengerService.getSession().sendTypingNotification(ChatWindowFragment.this.friendId, true);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        @Override
        public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
        }

        @Override
        public void afterTextChanged(final Editable s) {
        }
    };
    View.OnClickListener btnSend_Click = new OnClickListener() {

        @Override
        public void onClick(final View v) {
            sendIM();
        }
    };

    private void sendIM() {
        String sender = MessengerService.getSession().getLoginID().getId();
        String message = this.txtMessage.getText().toString();
        Date timeStamp = Calendar.getInstance().getTime();
        IM im = new IM(sender, message, timeStamp);

        if (im.getMessage().equals("")
                || MessengerService.getSession().getSessionStatus() != SessionState.LOGGED_ON)
            return;
        try {
            MessengerService.getSession().sendMessage(this.friendId, im.getMessage());
            MessengerService.addIm(this.getActivity(), this.friendId, im);
            this.listAdapter.notifyDataSetChanged();
            TextKeyListener.clear(this.txtMessage.getText()); // to prevent the Android's bug.
            // if we use setText(""), the EditText will not show typed characters after a while!
            // strange bug, I confess
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private class NotificationCanceler extends Thread {
        public boolean reschedule = false;
        public boolean shouldRun = true;

        @Override
        public void run() {
            while (this.shouldRun) {
                if (ChatWindowFragment.this.isTypingSelf) {
                    while (this.reschedule)
                        try {
                            this.reschedule = false;
                            Thread.sleep(1000);
                            continue;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try {
                        ChatWindowFragment.this.isTypingSelf = false;
                        MessengerService.getSession().sendTypingNotification(ChatWindowFragment.this.friendId,
                                false);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    protected class ChatFragmentListener extends BroadcastReceiver {

        @Override
        public void onReceive(final Context context, final Intent intent) {
            if ((intent.getAction().equals(MessengerService.INTENT_NEW_IM)
                    || intent.getAction().equals(MessengerService.INTENT_BUZZ))
                    && intent.getExtras().getString(Utils.qualify("from")).equals(ChatWindowFragment.this.friendId))
                ChatWindowFragment.this.listAdapter.notifyDataSetChanged();
            else if (intent.getAction().equals(MessengerService.INTENT_LIST_CHANGED))
                ChatWindowFragment.this.listAdapter.notifyDataSetChanged();
            else if (intent.getAction().equals(MessengerService.INTENT_INSERT_SMILEY) && intent.getExtras()
                    .getString(Utils.qualify("from")).equals(ChatWindowFragment.this.friendId)) {
                String smiley = intent.getExtras().getString(Utils.qualify("symbol"));
                // insert the smiley symbol at the current cursor location
                int start = ChatWindowFragment.this.txtMessage.getSelectionStart();
                int end = ChatWindowFragment.this.txtMessage.getSelectionEnd();

                ChatWindowFragment.this.txtMessage.getText().replace(Math.min(start, end), Math.max(start, end),
                        smiley, 0, smiley.length());
            }
        }
    }
}