com.orangelabs.rcs.ri.messaging.chat.ChatView.java Source code

Java tutorial

Introduction

Here is the source code for com.orangelabs.rcs.ri.messaging.chat.ChatView.java

Source

/*******************************************************************************
 * Software Name : RCS IMS Stack
 *
 * Copyright (C) 2010 France Telecom S.A.
 *
 * 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 com.orangelabs.rcs.ri.messaging.chat;

import com.gsma.services.rcs.Geoloc;
import com.gsma.services.rcs.RcsServiceException;
import com.gsma.services.rcs.chat.ChatLog;
import com.gsma.services.rcs.chat.ChatService;
import com.gsma.services.rcs.contact.ContactId;
import com.gsma.services.rcs.filetransfer.FileTransferLog;
import com.gsma.services.rcs.filetransfer.FileTransferService;
import com.gsma.services.rcs.history.HistoryLog;
import com.gsma.services.rcs.history.HistoryUriBuilder;

import com.orangelabs.rcs.api.connection.ConnectionManager.RcsServiceName;
import com.orangelabs.rcs.api.connection.utils.ExceptionUtil;
import com.orangelabs.rcs.api.connection.utils.RcsFragmentActivity;
import com.orangelabs.rcs.ri.R;
import com.orangelabs.rcs.ri.messaging.geoloc.EditGeoloc;
import com.orangelabs.rcs.ri.utils.LogUtils;
import com.orangelabs.rcs.ri.utils.RcsContactUtil;

import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

/**
 * Chat view
 *
 * @author yplo6403
 */
public abstract class ChatView extends RcsFragmentActivity
        implements LoaderManager.LoaderCallbacks<Cursor>, IChatView {
    /**
     * The loader's unique ID. Loader IDs are specific to the Activity in which they reside.
     */
    protected static final int LOADER_ID = 1;

    private final static int SELECT_GEOLOCATION = 0;

    private static final String LOGTAG = LogUtils.getTag(ChatView.class.getSimpleName());

    /**
     * The adapter that binds data to the ListView
     */
    protected ChatCursorAdapter mAdapter;

    /**
     * Message composer
     */
    protected EditText mComposeText;

    /**
     * Utility class to manage the is-composing status
     */
    protected IsComposingManager mComposingManager;

    /**
     * UI handler
     */
    protected Handler mHandler = new Handler();

    protected ChatService mChatService;

    protected Uri mUriHistoryProvider;

    protected FileTransferService mFileTransferService;

    private ChatCursorObserver mObserver;

    public static String sChatIdOnForeground;

    /**
     * Chat message projection
     */
    // @formatter:off
    protected static final String[] PROJ_CHAT_MSG = new String[] { HistoryLog.BASECOLUMN_ID, HistoryLog.ID,
            HistoryLog.PROVIDER_ID, HistoryLog.MIME_TYPE, HistoryLog.CONTENT, HistoryLog.TIMESTAMP,
            HistoryLog.STATUS, HistoryLog.DIRECTION, HistoryLog.CONTACT, HistoryLog.EXPIRED_DELIVERY,
            HistoryLog.FILENAME, HistoryLog.FILESIZE, HistoryLog.TRANSFERRED, HistoryLog.REASON_CODE };
    // @formatter:on

    /**
     * Query sort order
     */
    protected final static String ORDER_CHAT_MSG = HistoryLog.TIMESTAMP + " ASC";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /* Set layout */
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.chat_view);

        initialize();

        HistoryUriBuilder uriBuilder = new HistoryUriBuilder(HistoryLog.CONTENT_URI);
        uriBuilder.appendProvider(ChatLog.Message.HISTORYLOG_MEMBER_ID);
        uriBuilder.appendProvider(FileTransferLog.HISTORYLOG_MEMBER_ID);
        mUriHistoryProvider = uriBuilder.build();

        /* Set message composer callbacks */
        mComposeText = (EditText) findViewById(R.id.userText);
        mComposeText.setOnKeyListener(new OnKeyListener() {

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (KeyEvent.ACTION_DOWN != event.getAction()) {
                    return false;

                }
                switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_CENTER:
                case KeyEvent.KEYCODE_ENTER:
                    sendText();
                    return true;
                }
                return false;
            }
        });

        mComposeText.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // Check if the text is not null.
                // we do not wish to consider putting the edit text back to null
                // (like when sending message), is having activity
                if (!TextUtils.isEmpty(s)) {
                    // Warn the composing manager that we have some activity
                    if (mComposingManager != null) {
                        mComposingManager.hasActivity();
                    }
                }
            }

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

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        /* Set send button listener */
        Button sendBtn = (Button) findViewById(R.id.send_button);
        sendBtn.setOnClickListener(new OnClickListener() {

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

        /* Initialize the adapter. */
        mAdapter = new ChatCursorAdapter(this, isSingleChat());

        // Associate the list adapter with the ListView.
        ListView listView = (ListView) findViewById(android.R.id.list);
        listView.setAdapter(mAdapter);
        registerForContextMenu(listView);

        if (!isServiceConnected(RcsServiceName.CHAT, RcsServiceName.CONTACT, RcsServiceName.CAPABILITY,
                RcsServiceName.FILE_TRANSFER)) {
            showMessageThenExit(R.string.label_service_not_available);
            return;
        }
        startMonitorServices(RcsServiceName.CHAT, RcsServiceName.CONTACT, RcsServiceName.CAPABILITY,
                RcsServiceName.FILE_TRANSFER);
        mChatService = getChatApi();
        mFileTransferService = getFileTransferApi();
        processIntent(getIntent());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (isServiceConnected(RcsServiceName.CHAT) && mChatService != null) {
            try {
                removeChatEventListener(mChatService);
            } catch (RcsServiceException e) {
                Log.w(LOGTAG, ExceptionUtil.getFullStackTrace(e));
            }
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // Replace the value of intent
        setIntent(intent);
        if (isServiceConnected(RcsServiceName.CHAT, RcsServiceName.CONTACT, RcsServiceName.FILE_TRANSFER)) {
            processIntent(intent);
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if (LOADER_ID != loader.getId()) {
            return;
        }

        /*
         * The asynchronous load is complete and the data is now available for use. Only now can we
         * associate the queried Cursor with the CursorAdapter.
         */
        mAdapter.swapCursor(cursor);
        /**
         * Registering content observer for chat message and file transfer content URIs. When these
         * content URIs will change, this will notify the loader to reload its data.
         */
        if (mObserver != null && !mObserver.getLoader().equals(loader)) {
            ContentResolver resolver = getContentResolver();
            resolver.unregisterContentObserver(mObserver);
            resolver.unregisterContentObserver(mObserver);
            mObserver = null;
        }
        if (mObserver == null) {
            if (LogUtils.isActive) {
                Log.d(LOGTAG, "onLoadFinished: register content observer");
            }
            mObserver = new ChatCursorObserver(new Handler(), loader);
            ContentResolver resolver = getContentResolver();
            resolver.registerContentObserver(ChatLog.Message.CONTENT_URI, true, mObserver);
            resolver.registerContentObserver(FileTransferLog.CONTENT_URI, true, mObserver);
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        /*
         * For whatever reason, the Loader's data is now unavailable. Remove any references to the
         * old data by replacing it with a null Cursor.
         */
        mAdapter.swapCursor(null);
    }

    private void sendText() {
        String text = mComposeText.getText().toString();
        if (TextUtils.isEmpty(text)) {
            return;
        }
        try {
            sendMessage(text);
            /* Warn the composing manager that the message was sent */
            mComposingManager.messageWasSent();
            mComposeText.setText(null);

        } catch (RcsServiceException e) {
            showExceptionThenExit(e);
        }

    }

    private void sendGeoloc(Geoloc geoloc) {
        try {
            sendMessage(geoloc);

        } catch (RcsServiceException e) {
            showExceptionThenExit(e);
        }
    }

    /**
     * Add quick text
     */
    protected void addQuickText() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.label_select_quicktext);
        builder.setCancelable(true);
        builder.setItems(R.array.select_quicktext, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                String[] items = getResources().getStringArray(R.array.select_quicktext);
                mComposeText.append(items[which]);
            }
        });
        registerDialog(builder.show());
    }

    /**
     * Get a geoloc
     */
    protected void getGeoLoc() {
        // Start a new activity to send a geolocation
        startActivityForResult(new Intent(this, EditGeoloc.class), SELECT_GEOLOCATION);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }
        switch (requestCode) {
        case SELECT_GEOLOCATION:
            Geoloc geoloc = data.getParcelableExtra(EditGeoloc.EXTRA_GEOLOC);
            sendGeoloc(geoloc);
            break;
        }
    }

    /**
     * Display composing event for contact
     * 
     * @param contact the contact ID
     * @param status True if contact is composing
     */
    protected void displayComposingEvent(final ContactId contact, final boolean status) {
        final String from = RcsContactUtil.getInstance(this).getDisplayName(contact);
        // Execute on UI handler since callback is executed from service
        mHandler.post(new Runnable() {
            public void run() {
                TextView view = (TextView) findViewById(R.id.isComposingText);
                if (status) {
                    // Display is-composing notification
                    view.setText(getString(R.string.label_contact_is_composing, from));
                    view.setVisibility(View.VISIBLE);
                } else {
                    // Hide is-composing notification
                    view.setVisibility(View.GONE);
                }
            }
        });
    }

    protected void setCursorLoader(boolean firstLoad) {
        if (firstLoad) {
            /*
             * Initialize the Loader with id '1' and callbacks 'mCallbacks'.
             */
            getSupportLoaderManager().initLoader(LOADER_ID, null, this);
        } else {
            /* We switched from one contact to another: reload history since */
            getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
        }
    }
}