ChatView.java
上传用户:szyujian
上传日期:2016-09-20
资源大小:320k
文件大小:47k
- /*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.android.im.app;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.Map;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.content.AsyncQueryHandler;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.res.Resources;
- import android.database.ContentObserver;
- import android.database.Cursor;
- import android.database.CursorIndexOutOfBoundsException;
- import android.database.DataSetObserver;
- import android.database.CharArrayBuffer;
- import android.graphics.Typeface;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Message;
- import android.os.RemoteException;
- import android.provider.Im;
- import android.text.TextUtils;
- import android.text.style.StyleSpan;
- import android.text.style.URLSpan;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AbsListView;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.CursorAdapter;
- import android.widget.EditText;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.AbsListView.OnScrollListener;
- import android.widget.AdapterView.OnItemClickListener;
- import com.android.im.IChatListener;
- import com.android.im.IChatSession;
- import com.android.im.IChatSessionListener;
- import com.android.im.IChatSessionManager;
- import com.android.im.IContactList;
- import com.android.im.IContactListListener;
- import com.android.im.IContactListManager;
- import com.android.im.IImConnection;
- import com.android.im.R;
- import com.android.im.app.adapter.ChatListenerAdapter;
- import com.android.im.app.adapter.ChatSessionListenerAdapter;
- import com.android.im.engine.Contact;
- import com.android.im.engine.ImConnection;
- import com.android.im.engine.ImErrorInfo;
- import com.android.im.plugin.BrandingResourceIDs;
- public class ChatView extends LinearLayout {
- // This projection and index are set for the query of active chats
- static final String[] CHAT_PROJECTION = {
- Im.Contacts._ID,
- Im.Contacts.ACCOUNT,
- Im.Contacts.PROVIDER,
- Im.Contacts.USERNAME,
- Im.Contacts.NICKNAME,
- Im.Contacts.TYPE,
- Im.Presence.PRESENCE_STATUS,
- Im.Chats.LAST_UNREAD_MESSAGE,
- };
- static final int CONTACT_ID_COLUMN = 0;
- static final int ACCOUNT_COLUMN = 1;
- static final int PROVIDER_COLUMN = 2;
- static final int USERNAME_COLUMN = 3;
- static final int NICKNAME_COLUMN = 4;
- static final int TYPE_COLUMN = 5;
- static final int PRESENCE_STATUS_COLUMN = 6;
- static final int LAST_UNREAD_MESSAGE_COLUMN = 7;
- static final String[] INVITATION_PROJECT = {
- Im.Invitation._ID,
- Im.Invitation.PROVIDER,
- Im.Invitation.SENDER,
- };
- static final int INVITATION_ID_COLUMN = 0;
- static final int INVITATION_PROVIDER_COLUMN = 1;
- static final int INVITATION_SENDER_COLUMN = 2;
- static final StyleSpan STYLE_BOLD = new StyleSpan(Typeface.BOLD);
- Markup mMarkup;
- Activity mScreen;
- ImApp mApp;
- SimpleAlertHandler mHandler;
- Cursor mCursor;
- private ImageView mStatusIcon;
- private TextView mTitle;
- /*package*/ListView mHistory;
- EditText mEdtInput;
- private Button mSendButton;
- private View mStatusWarningView;
- private ImageView mWarningIcon;
- private TextView mWarningText;
- private MessageAdapter mMessageAdapter;
- private IChatSessionManager mChatSessionMgr;
- private IChatSessionListener mChatSessionListener;
- private IChatSession mChatSession;
- private long mChatId;
- int mType;
- String mNickName;
- String mUserName;
- long mProviderId;
- long mAccountId;
- long mInvitationId;
- private int mPresenceStatus;
- private int mViewType;
- private static final int VIEW_TYPE_CHAT = 1;
- private static final int VIEW_TYPE_INVITATION = 2;
- private static final int VIEW_TYPE_SUBSCRIPTION = 3;
- private static final long SHOW_TIME_STAMP_INTERVAL = 60 * 1000; // 1 minute
- private static final int QUERY_TOKEN = 10;
- // Async QueryHandler
- private final class QueryHandler extends AsyncQueryHandler {
- public QueryHandler(Context context) {
- super(context.getContentResolver());
- }
- @Override
- protected void onQueryComplete(int token, Object cookie, Cursor c) {
- Cursor cursor = new DeltaCursor(c);
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("onQueryComplete: cursor.count=" + cursor.getCount());
- }
- mMessageAdapter.changeCursor(cursor);
- }
- }
- private QueryHandler mQueryHandler;
- private class RequeryCallback implements Runnable {
- public void run() {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("RequeryCallback");
- }
- requeryCursor();
- }
- }
- private RequeryCallback mRequeryCallback = null;
- private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (!(view instanceof MessageView)) {
- return;
- }
- URLSpan[] links = ((MessageView)view).getMessageLinks();
- if (links.length == 0){
- return;
- }
- final ArrayList<String> linkUrls = new ArrayList<String>(links.length);
- for (URLSpan u : links) {
- linkUrls.add(u.getURL());
- }
- ArrayAdapter<String> a = new ArrayAdapter<String>(mScreen,
- android.R.layout.select_dialog_item, linkUrls);
- AlertDialog.Builder b = new AlertDialog.Builder(mScreen);
- b.setTitle(R.string.select_link_title);
- b.setCancelable(true);
- b.setAdapter(a, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- Uri uri = Uri.parse(linkUrls.get(which));
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- mScreen.startActivity(intent);
- }
- });
- b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- b.show();
- }
- };
- private IChatListener mChatListener = new ChatListenerAdapter() {
- @Override
- public void onIncomingMessage(IChatSession ses,
- com.android.im.engine.Message msg) {
- scheduleRequery(0);
- }
- @Override
- public void onContactJoined(IChatSession ses, Contact contact) {
- scheduleRequery(0);
- }
- @Override
- public void onContactLeft(IChatSession ses, Contact contact) {
- scheduleRequery(0);
- }
- @Override
- public void onSendMessageError(IChatSession ses,
- com.android.im.engine.Message msg, ImErrorInfo error) {
- scheduleRequery(0);
- }
- };
- private Runnable mUpdateChatCallback = new Runnable() {
- public void run() {
- if (mCursor.requery() && mCursor.moveToFirst()) {
- updateChat();
- }
- }
- };
- private IContactListListener mContactListListener = new IContactListListener.Stub () {
- public void onAllContactListsLoaded() {
- }
- public void onContactChange(int type, IContactList list, Contact contact){
- }
- public void onContactError(int errorType, ImErrorInfo error,
- String listName, Contact contact) {
- }
- public void onContactsPresenceUpdate(Contact[] contacts) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
- log("onContactsPresenceUpdate()");
- }
- for (Contact c : contacts) {
- if (c.getAddress().getFullName().equals(mUserName)) {
- mHandler.post(mUpdateChatCallback);
- scheduleRequery(0);
- break;
- }
- }
- }
- };
- static final void log(String msg) {
- Log.d(ImApp.LOG_TAG, "<ChatView> " +msg);
- }
- public ChatView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mScreen = (Activity) context;
- mApp = ImApp.getApplication(mScreen);
- mHandler = new ChatViewHandler();
- }
- void registerForConnEvents() {
- mApp.registerForConnEvents(mHandler);
- }
- void unregisterForConnEvents() {
- mApp.unregisterForConnEvents(mHandler);
- }
- @Override
- protected void onFinishInflate() {
- mStatusIcon = (ImageView) findViewById(R.id.statusIcon);
- mTitle = (TextView) findViewById(R.id.title);
- mHistory = (ListView) findViewById(R.id.history);
- mEdtInput = (EditText) findViewById(R.id.edtInput);
- mSendButton = (Button)findViewById(R.id.btnSend);
- mHistory.setOnItemClickListener(mOnItemClickListener);
- mStatusWarningView = findViewById(R.id.warning);
- mWarningIcon = (ImageView)findViewById(R.id.warningIcon);
- mWarningText = (TextView)findViewById(R.id.warningText);
- Button acceptInvitation = (Button)findViewById(R.id.btnAccept);
- Button declineInvitation= (Button)findViewById(R.id.btnDecline);
- Button approveSubscription = (Button)findViewById(R.id.btnApproveSubscription);
- Button declineSubscription = (Button)findViewById(R.id.btnDeclineSubscription);
- acceptInvitation.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- acceptInvitation();
- }
- });
- declineInvitation.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- declineInvitation();
- }
- });
- approveSubscription.setOnClickListener(new OnClickListener(){
- public void onClick(View v) {
- approveSubscription();
- }
- });
- declineSubscription.setOnClickListener(new OnClickListener(){
- public void onClick(View v) {
- declineSubscription();
- }
- });
- mEdtInput.setOnKeyListener(new OnKeyListener(){
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- sendMessage();
- return true;
- case KeyEvent.KEYCODE_ENTER:
- if (event.isAltPressed()) {
- mEdtInput.append("n");
- } else {
- sendMessage();
- }
- return true;
- }
- }
- return false;
- }
- });
- mSendButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- sendMessage();
- }
- });
- }
- public void onResume(){
- if (mViewType == VIEW_TYPE_CHAT) {
- Cursor cursor = getMessageCursor();
- if (cursor == null) {
- startQuery();
- } else {
- requeryCursor();
- }
- updateWarningView();
- }
- registerChatListener();
- registerForConnEvents();
- }
- public void onPause(){
- Cursor cursor = getMessageCursor();
- if (cursor != null) {
- cursor.deactivate();
- }
- cancelRequery();
- if (mViewType == VIEW_TYPE_CHAT) {
- markAsRead();
- }
- unregisterChatListener();
- unregisterForConnEvents();
- unregisterChatSessionListener();
- }
- void updateChat() {
- setViewType(VIEW_TYPE_CHAT);
- long oldChatId = mChatId;
- updateContactInfo();
- setStatusIcon();
- setTitle();
- IImConnection conn = mApp.getConnection(mProviderId);
- if (conn == null) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) log("Connection has been signed out");
- mScreen.finish();
- return;
- }
- BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
- mHistory.setBackgroundDrawable(
- brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_CHAT_WATERMARK));
- if (mMarkup == null) {
- mMarkup = new Markup(brandingRes);
- }
- if (mMessageAdapter == null) {
- mMessageAdapter = new MessageAdapter(mScreen, null);
- mHistory.setAdapter(mMessageAdapter);
- }
- // only change the message adapter when we switch to another chat
- if (mChatId != oldChatId) {
- startQuery();
- mEdtInput.setText("");
- }
- updateWarningView();
- }
- private void updateContactInfo() {
- mChatId = mCursor.getLong(CONTACT_ID_COLUMN);
- mProviderId = mCursor.getLong(PROVIDER_COLUMN);
- mAccountId = mCursor.getLong(ACCOUNT_COLUMN);
- mPresenceStatus = mCursor.getInt(PRESENCE_STATUS_COLUMN);
- mType = mCursor.getInt(TYPE_COLUMN);
- mUserName = mCursor.getString(USERNAME_COLUMN);
- mNickName = mCursor.getString(NICKNAME_COLUMN);
- }
- private void setTitle() {
- if (mType == Im.Contacts.TYPE_GROUP) {
- final String[] projection = {Im.GroupMembers.NICKNAME};
- Uri memberUri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, mChatId);
- ContentResolver cr = mScreen.getContentResolver();
- Cursor c = cr.query(memberUri, projection, null, null, null);
- StringBuilder buf = new StringBuilder();
- if(c != null) {
- while(c.moveToNext()) {
- buf.append(c.getString(0));
- if(!c.isLast()) {
- buf.append(',');
- }
- }
- c.close();
- }
- mTitle.setText(mContext.getString(R.string.chat_with, buf.toString()));
- } else {
- mTitle.setText(mContext.getString(R.string.chat_with, mNickName));
- }
- }
- private void setStatusIcon() {
- if (mType == Im.Contacts.TYPE_GROUP) {
- // hide the status icon for group chat.
- mStatusIcon.setVisibility(GONE);
- } else {
- mStatusIcon.setVisibility(VISIBLE);
- BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
- int presenceResId = PresenceUtils.getStatusIconId(mPresenceStatus);
- mStatusIcon.setImageDrawable(brandingRes.getDrawable(presenceResId));
- }
- }
- public void bindChat(long chatId) {
- if (mCursor != null) {
- mCursor.deactivate();
- }
- Uri contactUri = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, chatId);
- mCursor = mScreen.managedQuery(contactUri, CHAT_PROJECTION, null, null);
- if (mCursor == null || !mCursor.moveToFirst()) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("Failed to query chat: " + chatId);
- }
- mScreen.finish();
- return;
- } else {
- mChatSession = getChatSession(mCursor);
- updateChat();
- registerChatListener();
- }
- }
- public void bindInvitation(long invitationId) {
- Uri uri = ContentUris.withAppendedId(Im.Invitation.CONTENT_URI, invitationId);
- ContentResolver cr = mScreen.getContentResolver();
- Cursor cursor = cr.query(uri, INVITATION_PROJECT, null, null, null);
- if (cursor == null || !cursor.moveToFirst()) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("Failed to query invitation: " + invitationId);
- }
- mScreen.finish();
- } else {
- setViewType(VIEW_TYPE_INVITATION);
- mInvitationId = cursor.getLong(INVITATION_ID_COLUMN);
- mProviderId = cursor.getLong(INVITATION_PROVIDER_COLUMN);
- String sender = cursor.getString(INVITATION_SENDER_COLUMN);
- TextView mInvitationText = (TextView)findViewById(R.id.txtInvitation);
- mInvitationText.setText(mContext.getString(R.string.invitation_prompt, sender));
- mTitle.setText(mContext.getString(R.string.chat_with, sender));
- }
- if (cursor != null) {
- cursor.close();
- }
- }
- public void bindSubscription(long providerId, String from) {
- mProviderId = providerId;
- mUserName = from;
- setViewType(VIEW_TYPE_SUBSCRIPTION);
- TextView text = (TextView)findViewById(R.id.txtSubscription);
- String displayableAddr = ImpsAddressUtils.getDisplayableAddress(from);
- text.setText(mContext.getString(R.string.subscription_prompt, displayableAddr));
- mTitle.setText(mContext.getString(R.string.chat_with, displayableAddr));
- }
- void acceptInvitation() {
- try {
- IImConnection conn = mApp.getConnection(mProviderId);
- if (conn != null) {
- // register a chat session listener and wait for a group chat
- // session to be created after we accept the invitation.
- registerChatSessionListener();
- conn.acceptInvitation(mInvitationId);
- }
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- void declineInvitation() {
- try {
- IImConnection conn = mApp.getConnection(mProviderId);
- if (conn != null) {
- conn.rejectInvitation(mInvitationId);
- }
- mScreen.finish();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- void approveSubscription() {
- IImConnection conn = mApp.getConnection(mProviderId);
- try {
- IContactListManager manager = conn.getContactListManager();
- manager.approveSubscription(mUserName);
- } catch (RemoteException ex) {
- mHandler.showServiceErrorAlert();
- }
- mScreen.finish();
- }
- void declineSubscription() {
- IImConnection conn = mApp.getConnection(mProviderId);
- try {
- IContactListManager manager = conn.getContactListManager();
- manager.declineSubscription(mUserName);
- } catch (RemoteException ex) {
- mHandler.showServiceErrorAlert();
- }
- mScreen.finish();
- }
- private void setViewType(int type) {
- mViewType = type;
- if (type == VIEW_TYPE_CHAT) {
- findViewById(R.id.invitationPanel).setVisibility(GONE);
- findViewById(R.id.subscription).setVisibility(GONE);
- setChatViewEnabled(true);
- } else if (type == VIEW_TYPE_INVITATION) {
- setChatViewEnabled(false);
- findViewById(R.id.invitationPanel).setVisibility(VISIBLE);
- findViewById(R.id.btnAccept).requestFocus();
- } else if (type == VIEW_TYPE_SUBSCRIPTION) {
- setChatViewEnabled(false);
- findViewById(R.id.subscription).setVisibility(VISIBLE);
- findViewById(R.id.btnApproveSubscription).requestFocus();
- }
- }
- private void setChatViewEnabled(boolean enabled) {
- mEdtInput.setEnabled(enabled);
- mSendButton.setEnabled(enabled);
- if (enabled) {
- mEdtInput.requestFocus();
- } else {
- mHistory.setAdapter(null);
- }
- }
- private void markAsRead() {
- ContentValues values = new ContentValues(1);
- values.put(Im.Chats.LAST_UNREAD_MESSAGE, (String)null);
- ContentResolver cr = mContext.getContentResolver();
- Uri uri = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, mChatId);
- cr.update(uri, values, null, null);
- }
- private void startQuery() {
- if (mQueryHandler == null) {
- mQueryHandler = new QueryHandler(mContext);
- } else {
- // Cancel any pending queries
- mQueryHandler.cancelOperation(QUERY_TOKEN);
- }
- Uri uri;
- if (Im.Contacts.TYPE_GROUP == mType) {
- uri = ContentUris.withAppendedId(Im.GroupMessages.CONTENT_URI_GROUP_MESSAGES_BY, mChatId);
- } else {
- uri = Im.Messages.getContentUriByContact(mProviderId, mAccountId, mUserName);
- }
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("queryCursor: uri=" + uri);
- }
- mQueryHandler.startQuery(QUERY_TOKEN, null,
- uri,
- null,
- null /* selection */,
- null /* selection args */,
- null);
- }
- void scheduleRequery(long interval) {
- if (mRequeryCallback == null) {
- mRequeryCallback = new RequeryCallback();
- } else {
- mHandler.removeCallbacks(mRequeryCallback);
- }
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("scheduleRequery");
- }
- mHandler.postDelayed(mRequeryCallback, interval);
- }
- void cancelRequery() {
- if (mRequeryCallback != null) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("cancelRequery");
- }
- mHandler.removeCallbacks(mRequeryCallback);
- mRequeryCallback = null;
- }
- }
- void requeryCursor() {
- if (mMessageAdapter.isScrolling()) {
- mMessageAdapter.setNeedRequeryCursor(true);
- return;
- }
- // TODO: async query?
- Cursor cursor = getMessageCursor();
- if (cursor != null) {
- cursor.requery();
- }
- }
- private Cursor getMessageCursor() {
- return mMessageAdapter == null ? null : mMessageAdapter.getCursor();
- }
- public void insertSmiley(String smiley) {
- mEdtInput.append(mMarkup.applyEmoticons(smiley));
- }
- public void closeChatSession() {
- if (mChatSession != null) {
- try {
- mChatSession.leave();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- } else {
- // the conversation is already closed, clear data in database
- ContentResolver cr = mContext.getContentResolver();
- cr.delete(ContentUris.withAppendedId(Im.Chats.CONTENT_URI, mChatId),
- null, null);
- }
- mScreen.finish();
- }
- public void viewProfile() {
- Uri data = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, mChatId);
- Intent intent = new Intent(Intent.ACTION_VIEW, data);
- mScreen.startActivity(intent);
- }
- public void blockContact() {
- // TODO: unify with codes in ContactListView
- DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener(){
- public void onClick(DialogInterface dialog, int whichButton) {
- try {
- IImConnection conn = mApp.getConnection(mProviderId);
- IContactListManager manager = conn.getContactListManager();
- manager.blockContact(mUserName);
- mScreen.finish();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- };
- Resources r = getResources();
- // The positive button is deliberately set as no so that
- // the no is the default value
- new AlertDialog.Builder(mContext)
- .setTitle(R.string.confirm)
- .setMessage(r.getString(R.string.confirm_block_contact, mNickName))
- .setPositiveButton(R.string.no, null) // default button
- .setNegativeButton(R.string.yes, confirmListener)
- .setCancelable(false)
- .show();
- }
- public long getProviderId() {
- return mProviderId;
- }
- public long getAccountId() {
- return mAccountId;
- }
- public String getUserName() {
- return mUserName;
- }
- public long getChatId () {
- try {
- return mChatSession == null ? -1 : mChatSession.getId();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- return -1;
- }
- }
- public IChatSession getCurrentChatSession() {
- return mChatSession;
- }
- private IChatSessionManager getChatSessionManager(long providerId) {
- if (mChatSessionMgr == null) {
- IImConnection conn = mApp.getConnection(providerId);
- if (conn != null) {
- try {
- mChatSessionMgr = conn.getChatSessionManager();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- }
- return mChatSessionMgr;
- }
- private IChatSession getChatSession(Cursor cursor) {
- long providerId = cursor.getLong(PROVIDER_COLUMN);
- String username = cursor.getString(USERNAME_COLUMN);
- IChatSessionManager sessionMgr = getChatSessionManager(providerId);
- if (sessionMgr != null) {
- try {
- return sessionMgr.getChatSession(username);
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- return null;
- }
- boolean isGroupChat() {
- return Im.Contacts.TYPE_GROUP == mType;
- }
- void sendMessage() {
- String msg = mEdtInput.getText().toString();
- if (mChatSession != null && !TextUtils.isEmpty(msg.trim())) {
- try {
- mChatSession.sendMessage(msg);
- mEdtInput.setText("");
- mEdtInput.requestFocus();
- requeryCursor();
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- }
- void registerChatListener() {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("registerChatListener");
- }
- try {
- if (mChatSession != null) {
- mChatSession.registerChatListener(mChatListener);
- }
- IImConnection conn = mApp.getConnection(mProviderId);
- if (conn != null) {
- IContactListManager listMgr = conn.getContactListManager();
- listMgr.registerContactListListener(mContactListListener);
- }
- mApp.dismissNotifications(mProviderId);
- } catch (RemoteException e) {
- Log.w(ImApp.LOG_TAG, "<ChatView> registerChatListener fail:" + e.getMessage());
- }
- }
- void unregisterChatListener() {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("unregisterChatListener");
- }
- try {
- if (mChatSession != null) {
- mChatSession.unregisterChatListener(mChatListener);
- }
- IImConnection conn = mApp.getConnection(mProviderId);
- if (conn != null) {
- IContactListManager listMgr = conn.getContactListManager();
- listMgr.unregisterContactListListener(mContactListListener);
- }
- } catch (RemoteException e) {
- Log.w(ImApp.LOG_TAG, "<ChatView> unregisterChatListener fail:" + e.getMessage());
- }
- }
- void registerChatSessionListener() {
- IChatSessionManager sessionMgr = getChatSessionManager(mProviderId);
- if (sessionMgr != null) {
- mChatSessionListener = new ChatSessionListener();
- try {
- sessionMgr.registerChatSessionListener(mChatSessionListener);
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- }
- void unregisterChatSessionListener() {
- if (mChatSessionListener != null) {
- try {
- IChatSessionManager sessionMgr = getChatSessionManager(mProviderId);
- sessionMgr.unregisterChatSessionListener(mChatSessionListener);
- // We unregister the listener when the chat session we are
- // waiting for has been created or the activity is stopped.
- // Clear the listener so that we won't unregister the listener
- // twice.
- mChatSessionListener = null;
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- }
- void updateWarningView() {
- int visibility = View.GONE;
- int iconVisibility = View.GONE;
- String message = null;
- boolean isConnected;
- try {
- IImConnection conn = mApp.getConnection(mProviderId);
- isConnected = (conn == null) ? false
- : conn.getState() != ImConnection.SUSPENDED;
- } catch (RemoteException e) {
- // do nothing
- return;
- }
- if (isConnected) {
- if (mType == Im.Contacts.TYPE_TEMPORARY) {
- visibility = View.VISIBLE;
- message = mContext.getString(R.string.contact_not_in_list_warning, mNickName);
- } else if (mPresenceStatus == Im.Presence.OFFLINE) {
- visibility = View.VISIBLE;
- message = mContext.getString(R.string.contact_offline_warning, mNickName);
- }
- } else {
- visibility = View.VISIBLE;
- iconVisibility = View.VISIBLE;
- message = mContext.getString(R.string.disconnected_warning);
- }
- mStatusWarningView.setVisibility(visibility);
- if (visibility == View.VISIBLE) {
- mWarningIcon.setVisibility(iconVisibility);
- mWarningText.setText(message);
- }
- }
- private final class ChatViewHandler extends SimpleAlertHandler {
- public ChatViewHandler() {
- super(mScreen);
- }
- @Override
- public void handleMessage(Message msg) {
- long providerId = ((long)msg.arg1 << 32) | msg.arg2;
- if (providerId != mProviderId) {
- return;
- }
- switch(msg.what) {
- case ImApp.EVENT_CONNECTION_LOGGED_IN:
- log("Connection resumed");
- updateWarningView();
- return;
- case ImApp.EVENT_CONNECTION_SUSPENDED:
- log("Connection suspended");
- updateWarningView();
- return;
- }
- super.handleMessage(msg);
- }
- }
- class ChatSessionListener extends ChatSessionListenerAdapter {
- @Override
- public void onChatSessionCreated(IChatSession session) {
- try {
- if (session.isGroupChatSession()) {
- final long id = session.getId();
- unregisterChatSessionListener();
- mHandler.post(new Runnable() {
- public void run() {
- bindChat(id);
- }});
- }
- } catch (RemoteException e) {
- mHandler.showServiceErrorAlert();
- }
- }
- }
- public static class DeltaCursor implements Cursor {
- static final String DELTA_COLUMN_NAME = "delta";
- private Cursor mCursor;
- private String[] mColumnNames;
- private int mDateColumn = -1;
- private int mDeltaColumn = -1;
- DeltaCursor(Cursor cursor) {
- mCursor = cursor;
- String[] columnNames = cursor.getColumnNames();
- int len = columnNames.length;
- mColumnNames = new String[len + 1];
- for (int i = 0 ; i < len ; i++) {
- mColumnNames[i] = columnNames[i];
- if (mColumnNames[i].equals(Im.BaseMessageColumns.DATE)) {
- mDateColumn = i;
- }
- }
- mDeltaColumn = len;
- mColumnNames[mDeltaColumn] = DELTA_COLUMN_NAME;
- //if (DBG) log("##### DeltaCursor constructor: mDeltaColumn=" +
- // mDeltaColumn + ", columnName=" + mColumnNames[mDeltaColumn]);
- }
- public int getCount() {
- return mCursor.getCount();
- }
- public int getPosition() {
- return mCursor.getPosition();
- }
- public boolean move(int offset) {
- return mCursor.move(offset);
- }
- public boolean moveToPosition(int position) {
- return mCursor.moveToPosition(position);
- }
- public boolean moveToFirst() {
- return mCursor.moveToFirst();
- }
- public boolean moveToLast() {
- return mCursor.moveToLast();
- }
- public boolean moveToNext() {
- return mCursor.moveToNext();
- }
- public boolean moveToPrevious() {
- return mCursor.moveToPrevious();
- }
- public boolean isFirst() {
- return mCursor.isFirst();
- }
- public boolean isLast() {
- return mCursor.isLast();
- }
- public boolean isBeforeFirst() {
- return mCursor.isBeforeFirst();
- }
- public boolean isAfterLast() {
- return mCursor.isAfterLast();
- }
- public boolean deleteRow() {
- return mCursor.deleteRow();
- }
- public int getColumnIndex(String columnName) {
- if (DELTA_COLUMN_NAME.equals(columnName)) {
- return mDeltaColumn;
- }
- int columnIndex = mCursor.getColumnIndex(columnName);
- return columnIndex;
- }
- public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
- if (DELTA_COLUMN_NAME.equals(columnName)) {
- return mDeltaColumn;
- }
- return mCursor.getColumnIndexOrThrow(columnName);
- }
- public String getColumnName(int columnIndex) {
- if (columnIndex == mDeltaColumn) {
- return DELTA_COLUMN_NAME;
- }
- return mCursor.getColumnName(columnIndex);
- }
- public int getColumnCount() {
- return mCursor.getColumnCount() + 1;
- }
- public boolean supportsUpdates() {
- return mCursor.supportsUpdates();
- }
- public boolean hasUpdates() {
- return mCursor.hasUpdates();
- }
- public boolean updateBlob(int columnIndex, byte[] value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateBlob(columnIndex, value);
- }
- public boolean updateString(int columnIndex, String value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateString(columnIndex, value);
- }
- public boolean updateShort(int columnIndex, short value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateShort(columnIndex, value);
- }
- public boolean updateInt(int columnIndex, int value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateInt(columnIndex, value);
- }
- public boolean updateLong(int columnIndex, long value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateLong(columnIndex, value);
- }
- public boolean updateFloat(int columnIndex, float value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateFloat(columnIndex, value);
- }
- public boolean updateDouble(int columnIndex, double value) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateDouble(columnIndex, value);
- }
- public boolean updateToNull(int columnIndex) {
- if (columnIndex == mDeltaColumn) {
- return false;
- }
- return mCursor.updateToNull(columnIndex);
- }
- public boolean commitUpdates() {
- return mCursor.commitUpdates();
- }
- public boolean commitUpdates(Map<? extends Long,
- ? extends Map<String,Object>> values) {
- return mCursor.commitUpdates(values);
- }
- public void abortUpdates() {
- mCursor.abortUpdates();
- }
- public void deactivate() {
- mCursor.deactivate();
- }
- public boolean requery() {
- return mCursor.requery();
- }
- public void close() {
- mCursor.close();
- }
- public boolean isClosed() {
- return mCursor.isClosed();
- }
- public void registerContentObserver(ContentObserver observer) {
- mCursor.registerContentObserver(observer);
- }
- public void unregisterContentObserver(ContentObserver observer) {
- mCursor.unregisterContentObserver(observer);
- }
- public void registerDataSetObserver(DataSetObserver observer) {
- mCursor.registerDataSetObserver(observer);
- }
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mCursor.unregisterDataSetObserver(observer);
- }
- public void setNotificationUri(ContentResolver cr, Uri uri) {
- mCursor.setNotificationUri(cr, uri);
- }
- public boolean getWantsAllOnMoveCalls() {
- return mCursor.getWantsAllOnMoveCalls();
- }
- public Bundle getExtras() {
- return mCursor.getExtras();
- }
- public Bundle respond(Bundle extras) {
- return mCursor.respond(extras);
- }
- public String[] getColumnNames() {
- return mColumnNames;
- }
- private void checkPosition() {
- int pos = mCursor.getPosition();
- int count = mCursor.getCount();
- if (-1 == pos || count == pos) {
- throw new CursorIndexOutOfBoundsException(pos, count);
- }
- }
- public byte[] getBlob(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return null;
- }
- return mCursor.getBlob(column);
- }
- public String getString(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- long value = getDeltaValue();
- return Long.toString(value);
- }
- return mCursor.getString(column);
- }
- public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
- checkPosition();
- if (columnIndex == mDeltaColumn) {
- long value = getDeltaValue();
- String strValue = Long.toString(value);
- int len = strValue.length();
- char[] data = buffer.data;
- if (data == null || data.length < len) {
- buffer.data = strValue.toCharArray();
- } else {
- strValue.getChars(0, len, data, 0);
- }
- buffer.sizeCopied = strValue.length();
- } else {
- mCursor.copyStringToBuffer(columnIndex, buffer);
- }
- }
- public short getShort(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return (short)getDeltaValue();
- }
- return mCursor.getShort(column);
- }
- public int getInt(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return (int)getDeltaValue();
- }
- return mCursor.getInt(column);
- }
- public long getLong(int column) {
- //if (DBG) log("DeltaCursor.getLong: column=" + column + ", mDeltaColumn=" + mDeltaColumn);
- checkPosition();
- if (column == mDeltaColumn) {
- return getDeltaValue();
- }
- return mCursor.getLong(column);
- }
- public float getFloat(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return getDeltaValue();
- }
- return mCursor.getFloat(column);
- }
- public double getDouble(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return getDeltaValue();
- }
- return mCursor.getDouble(column);
- }
- public boolean isNull(int column) {
- checkPosition();
- if (column == mDeltaColumn) {
- return false;
- }
- return mCursor.isNull(column);
- }
- private long getDeltaValue() {
- int pos = mCursor.getPosition();
- //Log.i(LOG_TAG, "getDeltaValue: mPos=" + mPos);
- long t2, t1;
- if (pos == getCount()-1) {
- t1 = mCursor.getLong(mDateColumn);
- t2 = System.currentTimeMillis();
- } else {
- mCursor.moveToPosition(pos + 1);
- t2 = mCursor.getLong(mDateColumn);
- mCursor.moveToPosition(pos);
- t1 = mCursor.getLong(mDateColumn);
- }
- return t2 - t1;
- }
- }
- private class MessageAdapter extends CursorAdapter implements AbsListView.OnScrollListener {
- private int mScrollState;
- private boolean mNeedRequeryCursor;
- private int mContactColumn;
- private int mBodyColumn;
- private int mDateColumn;
- private int mTypeColumn;
- private int mErrCodeColumn;
- private int mDeltaColumn;
- private ChatBackgroundMaker mBgMaker;
- private LayoutInflater mInflater;
- public MessageAdapter(Activity context, Cursor c) {
- super(context, c, false);
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mBgMaker = new ChatBackgroundMaker(context);
- if (c != null) {
- resolveColumnIndex(c);
- }
- }
- private void resolveColumnIndex(Cursor c) {
- mContactColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.CONTACT);
- mBodyColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.BODY);
- mDateColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.DATE);
- mTypeColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.TYPE);
- mErrCodeColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.ERROR_CODE);
- mDeltaColumn = c.getColumnIndexOrThrow(DeltaCursor.DELTA_COLUMN_NAME);
- }
- @Override
- public void changeCursor(Cursor cursor) {
- super.changeCursor(cursor);
- if (cursor != null) {
- resolveColumnIndex(cursor);
- }
- }
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.new_message_item, parent, false);
- }
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- MessageView chatMsgView = (MessageView) view;
- int type = cursor.getInt(mTypeColumn);
- String contact = isGroupChat() ? cursor.getString(mContactColumn) : mNickName;
- String body = cursor.getString(mBodyColumn);
- long delta = cursor.getLong(mDeltaColumn);
- boolean showTimeStamp = (delta > SHOW_TIME_STAMP_INTERVAL);
- Date date = showTimeStamp ? new Date(cursor.getLong(mDateColumn)) : null;
- switch (type) {
- case Im.MessageType.INCOMING:
- chatMsgView.bindIncomingMessage(contact, body, date, mMarkup, isScrolling());
- break;
- case Im.MessageType.OUTGOING:
- case Im.MessageType.POSTPONED:
- int errCode = cursor.getInt(mErrCodeColumn);
- if (errCode != 0) {
- chatMsgView.bindErrorMessage(errCode);
- } else {
- chatMsgView.bindOutgoingMessage(body, date, mMarkup, isScrolling());
- }
- break;
- default:
- chatMsgView.bindPresenceMessage(contact, type, isGroupChat(), isScrolling());
- }
- if (!isScrolling()) {
- mBgMaker.setBackground(chatMsgView, contact, type);
- }
- // if showTimeStamp is false for the latest message, then set a timer to query the
- // cursor again in a minute, so we can update the last message timestamp if no new
- // message is received
- if (cursor.getPosition() == cursor.getCount()-1) {
- if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
- log("delta = " + delta + ", showTs=" + showTimeStamp);
- }
- if (!showTimeStamp) {
- scheduleRequery(SHOW_TIME_STAMP_INTERVAL);
- } else {
- cancelRequery();
- }
- }
- }
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
- int totalItemCount) {
- // do nothing
- }
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- int oldState = mScrollState;
- mScrollState = scrollState;
- if (oldState == OnScrollListener.SCROLL_STATE_FLING) {
- if (mNeedRequeryCursor) {
- requeryCursor();
- } else {
- notifyDataSetChanged();
- }
- }
- }
- boolean isScrolling() {
- return mScrollState == OnScrollListener.SCROLL_STATE_FLING;
- }
- void setNeedRequeryCursor(boolean requeryCursor) {
- mNeedRequeryCursor = requeryCursor;
- }
- }
- }