/*
* 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.mms.ui;
import static android.content.res.Configuration.KEYBOARDHIDDEN_NO;
import static com.android.mms.transaction.ProgressCallbackEntity.PROGRESS_ABORT;
import static com.android.mms.transaction.ProgressCallbackEntity.PROGRESS_COMPLETE;
import static com.android.mms.transaction.ProgressCallbackEntity.PROGRESS_START;
import static com.android.mms.transaction.ProgressCallbackEntity.PROGRESS_STATUS_ACTION;
import static com.android.mms.ui.MessageListAdapter.COLUMN_ID;
import static com.android.mms.ui.MessageListAdapter.COLUMN_MMS_LOCKED;
import static com.android.mms.ui.MessageListAdapter.COLUMN_MSG_TYPE;
import static com.android.mms.ui.MessageListAdapter.COLUMN_SMS_PHONE_ID;
import static com.android.mms.ui.MessageListAdapter.PROJECTION;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.apache.http.util.EncodingUtils;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ProgressDialog;
import android.app.SimChooserDialog;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.AsyncQueryHandler;
import android.content.BroadcastReceiver;
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.IntentFilter;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SqliteWrapper;
import android.drm.mobile1.DrmException;
import android.drm.mobile1.DrmRawContent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
import android.media.CamcorderProfile;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.pim.vcard.VCardBuilder;
import android.pim.vcard.VCardComposer;
import android.pim.vcard.VCardConfig;
import android.pim.vcard.VCardComposer.HandlerForOutputStream;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.DrmStore;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Sms;
import android.provider.Telephony.MmsSms.PendingMessages;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.text.Annotation;
import android.text.ClipboardManager;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.Time;
import android.text.method.TextKeyListener;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.Config;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.view.View.OnKeyListener;
import android.view.inputmethod.InputMethodManager;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.LinearLayout.LayoutParams;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.mms.ExceedMessageSizeException;
import com.android.mms.LogTag;
import com.android.mms.MmsConfig;
import com.android.mms.R;
import com.android.mms.ResolutionException;
import com.android.mms.TempFileProvider;
import com.android.mms.UnsupportContentTypeException;
import com.android.mms.data.Contact;
import com.android.mms.data.ContactList;
import com.android.mms.data.Conversation;
import com.android.mms.data.WorkingMessage;
import com.android.mms.data.WorkingMessage.MessageStatusListener;
import com.google.android.mms.ContentType;
import com.google.android.mms.pdu.EncodedStringValue;
import com.google.android.mms.MmsException;
import com.google.android.mms.pdu.PduBody;
import com.google.android.mms.pdu.PduHeaders;
import com.google.android.mms.pdu.PduPart;
import com.google.android.mms.pdu.PduPersister;
import com.google.android.mms.pdu.SendReq;
import com.android.mms.model.ImageModel;
import com.android.mms.model.Model;
import com.android.mms.model.TextModel;
import com.android.mms.model.SlideModel;
import com.android.mms.model.SlideshowModel;
import com.android.mms.model.VcardModel;
import com.android.mms.transaction.MessageSender;
import com.android.mms.transaction.MessagingNotification;
import com.android.mms.transaction.MmsMessageSender;
import com.android.mms.transaction.SmsReceiver;
import com.android.mms.transaction.SmsReceiverService;
import com.android.mms.transaction.TransactionService;
import com.android.mms.transaction.TransactionServiceHelper;
import com.android.mms.ui.MessageUtils.ResizeImageResultCallback;
import com.android.mms.ui.RecipientsEditor.RecipientContextMenuInfo;
import com.android.mms.util.DownloadManager;
import com.android.mms.util.FeatureSwitch;
import com.android.mms.util.SendingProgressTokenManager;
import com.android.mms.util.SmileyParser;
import com.android.mms.util.ZoomViewUtil;
import android.text.InputFilter.LengthFilter;
import com.android.internal.telephony.PhoneFactory;
import com.android.mms.ui.ConversationList;// by lai
import android.view.MotionEvent; //by lai
import android.widget.ScrollView; //by lai
import android.view.View.OnTouchListener; //by lai
import android.preference.PreferenceManager;//by lai
/**
* This is the main UI for:
* 1. Composing a new message;
* 2. Viewing/managing message history of a conversation.
*
* This activity can handle following parameters from the intent
* by which it's launched.
* thread_id long Identify the conversation to be viewed. When creating a
* new message, this parameter shouldn't be present.
* msg_uri Uri The message which should be opened for editing in the editor.
* address String The addresses of the recipients in current conversation.
* exit_on_sent boolean Exit this activity after the message is sent.
*/
public class ComposeMessageActivity extends Activity
implements View.OnClickListener, TextView.OnEditorActionListener,
MessageStatusListener, Contact.UpdateListener, ZoomViewUtil.TextResizeable {
public static final int REQUEST_CODE_ATTACH_IMAGE = 10;
public static final int REQUEST_CODE_TAKE_PICTURE = 11;
public static final int REQUEST_CODE_ATTACH_VIDEO = 12;
public static final int REQUEST_CODE_TAKE_VIDEO = 13;
public static final int REQUEST_CODE_ATTACH_SOUND = 14;
public static final int REQUEST_CODE_RECORD_SOUND = 15;
public static final int REQUEST_CODE_CREATE_SLIDESHOW = 16;
public static final int REQUEST_CODE_ECM_EXIT_DIALOG = 17;
public static final int REQUEST_CODE_ADD_CONTACT = 18;
public static final int REQUEST_CODE_ADD_ATTACHMENT = 19;
private static final String TAG = "Mms/compose";
private static final boolean DEBUG = true;
private static final boolean TRACE = false;
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
private static final String EXTRA_IS_VIDEOCALL = "android.phone.extra.IS_VIDEOCALL";
private String mPhoneNumForMms; //by lai
// Menu ID
private static final int MENU_ADD_SUBJECT = 0;
private static final int MENU_DELETE_THREAD = 1;
private static final int MENU_ADD_ATTACHMENT = 2;
private static final int MENU_DISCARD = 3;
private static final int MENU_SEND = 4;
private static final int MENU_CALL_RECIPIENT = 5;
private static final int MENU_VIDEOCALL_RECIPIENT = 6;
private static final int MENU_CONVERSATION_LIST = 7;
// Context menu ID
private static final int MENU_VIEW_CONTACT = 12;
private static final int MENU_ADD_TO_CONTACTS = 13;
private static final int MENU_EDIT_MESSAGE = 14;
private static final int MENU_VIEW_SLIDESHOW = 16;
private static final int MENU_VIEW_MESSAGE_DETAILS = 17;
private static final int MENU_DELETE_MESSAGE = 18;
private static final int MENU_SEARCH = 19;
private static final int MENU_DELIVERY_REPORT = 20;
private static final int MENU_FORWARD_MESSAGE = 21;
private static final int MENU_CALL_BACK = 22;
private static final int MENU_VIDEOCALL_BACK = 23;
private static final int MENU_SEND_EMAIL = 24;
private static final int MENU_COPY_MESSAGE_TEXT = 25;
private static final int MENU_COPY_TO_SDCARD = 26;
private static final int MENU_INSERT_SMILEY = 27;
private static final int MENU_ADD_ADDRESS_TO_CONTACTS = 28;
private static final int MENU_LOCK_MESSAGE = 29;
private static final int MENU_UNLOCK_MESSAGE = 30;
private static final int MENU_COPY_TO_DRM_PROVIDER = 31;
private static final int MENU_COPY_MESSAGE_TO_SIM = 32;
private static final int MENU_SEND_SMS = 33;
private static final int MENU_COPY_MMS_MESSAGE_TEXT = 34;
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
private static final int MENU_SAVE_BOOKMARK = 34;
private static final String ACTION_SAVE_BOOKMARK = "sprd.intent.action.SAVE_BOOKMARK";
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
private static final int MENU_RESEND_MESSAGE = 35;
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 begin =====
private static boolean IS_APPEND_MEDIA = true;
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 end =====
//private static final int RECIPIENTS_MAX_LENGTH = 312;
private static final int RECIPIENTS_MAX_LENGTH = 2000;
// the max muber of recipients to send message
private static final int RECIPIENTS_MAX_MUBER = 200;
private static final int MESSAGE_LIST_QUERY_TOKEN = 9527;
private static final int DELETE_MESSAGE_TOKEN = 9700;
private static final int CHARS_REMAINING_BEFORE_COUNTER_SHOWN = 10;
private static final long NO_DATE_FOR_DIALOG = -1L;
//yeezone:jinwei add limit of
private static final int LIMITED_MESSAGE_MAX_COUNT = 160;//modify from 140 to 160 for for wrong max message count 20110722
private static final int REQUESET_CODE_SELECT_CONTACTS = 1000;
private static final String EXIT_ECM_RESULT = "exit_ecm_result";
private static final int MODE_MMS_VCARD_CONTACTS = 8; //for include vcard
private ContentResolver mContentResolver;
private BackgroundQueryHandler mBackgroundQueryHandler;
private Conversation mConversation; // Conversation we are working in
private boolean mExitOnSent; // Should we finish() after sending a message?
private TextView mTitleLeft; //left of title
private TextView mTitleRight; //right of title
private View mTopPanel; // View containing the recipient and subject editors
private View mBottomPanel; // View containing the text editor, send button, ec.
private EditText mTextEditor; // Text editor to type your message into
private TextView mTextCounter; // Shows the number of characters used in text editor
private Button mSendButton; // Press to detonate
private Button mContactsSelectButton; // Press to select number from Contacts //yeezone:jinwei
private EditText mSubjectTextEditor; // Text editor for MMS subject
private AttachmentEditor mAttachmentEditor;
private SimChooserDialog mSimChooserDialg;
private TelephonyManager mTelephonyManager;
private MessageListView mMsgListView; // ListView for messages in this conversation
public MessageListAdapter mMsgListAdapter; // and its corresponding ListAdapter
private RecipientsEditor mRecipientsEditor; // UI control for editing recipients
private boolean mIsKeyboardOpen; // Whether the hardware keyboard is visible
private boolean mIsLandscape; // Whether we're in landscape mode
private boolean mPossiblePendingNotification; // If the message list has changed, we may have
// a pending notification to deal with.
private boolean mToastForDraftSave; // Whether to notify the user that a draft is being saved
private boolean mSentMessage; // true if the user has sent a message while in this
// activity. On a new compose message case, when the first
// message is sent is a MMS w/ attachment, the list blanks
// for a second before showing the sent message. But we'd
// think the message list is empty, thus show the recipients
// editor thinking it's a draft message. This flag should
// help clarify the situation.
private WorkingMessage mWorkingMessage; // The message currently being composed.
private AlertDialog mSmileyDialog;
private boolean mWaitingForSubActivity;
private int mLastRecipientCount; // Used for warning the user on too many recipients.
private AttachmentTypeSelectorAdapter mAttachmentTypeSelectorAdapter;
private boolean mSendingMessage; // Indicates the current message is sending, and shouldn't send again.
private Intent mAddContactIntent; // Intent used to add a new contact
// add save all send Contacts
// private ArrayList<ContentValues> list = new ArrayList<ContentValues>();/*delete for CR<NEWMS00135995> by luning at 11-11-04 */
private boolean[] mSmsReady = {false, false};
AlertDialog.Builder mAttachmentDialogBuilder;
AlertDialog mAttachmentDialog ;
//modify by dory.zheng for NEWMS00120648 at 15-09 begin
static final Uri DIVIDED_GROUP_URI=Uri.parse("content://"+ContactsContract.AUTHORITY+"/divided_group");
private final static int MODE_PICK = 0;
private static final int GROUP_ALL = 0;
private static final int GROUP_PHONE = 1;
private static final int GROUP_SIM = 2;
private static final int GROUP_SIM1 = 4;
private static final int GROUP_SIM2 = 5;
//modify by dory.zheng for NEWMS00120648 at 15-09 end
/* fixed CR<NEWMS119944 NEWMS119757 NEWMS119755 NEWMS120030 NEWMS119256> by lino release memory */
private Cursor mCursor;
private LinearLayout mContextView;
// private boolean mCreate;
private String mDebugRecipients;
private static final String INBOX = "inbox";
private static final String OUTBOX = "outbox";
private static final String SENT = "sent";
private static final String DRAFTS = "drafts";
private String boxmsgFlg = "";
private String boxmsgThreadId = "";
private String boxmsgMsgId = "";
private String boxType = "";
private String messageBody;
private boolean isLongPressSendFlg = false;
static final String MMS_LAUNCH_MODE_PATH = "/data/data/com.android.mms/launchmode";
private static final int GROUP_NAME_STUDENT = 0;
private static final int GROUP_NAME_FRIEND = 1;
private static final int GROUP_NAME_FAMILY = 2;
private static final int GROUP_NAME_COLLEAGUE = 3;
private boolean outboxEditMsgFlg = false;
private boolean is_vcard_adding = false;
private ProgressDialog mVcardProgressDialog = null;
private VcardProgressHandler mEventHandler = null;
//add for bug 17466
private boolean notificationFlg = false;
private ZoomViewUtil mZoom;
private static enum TextCompareResult {
NOEXCEED_ANY_SIZE,
EXCEED_MAX_MMS_SIZE,
EXCEED_MAX_TEXT_SIZE,
EXCEED_ORGINAL_MAX_MMS_SIZE;
}
private TextCompareResult mTxtCompareRst = TextCompareResult.NOEXCEED_ANY_SIZE;
private int mTxtLength = 0;
@SuppressWarnings("unused")
private static void log(String logMsg) {
Thread current = Thread.currentThread();
long tid = current.getId();
StackTraceElement[] stack = current.getStackTrace();
String methodName = stack[3].getMethodName();
// Prepend current thread ID and name of calling method to the message.
logMsg = "[" + tid + "] [" + methodName + "] " + logMsg;
Log.d(TAG, logMsg);
}
//==========================================================
// Inner classes
//==========================================================
private void editSlideshow() {
/* fixed HUAWEI BUG by luning at 2011.12.27 begin*/
if(mWorkingMessage.isDiscarded()){
mWorkingMessage.unDiscard();
}
/* fixed HUAWEI BUG by luning at 2011.12.27 end*/
Uri dataUri = mWorkingMessage.saveAsMms(false);
Intent intent = new Intent(this, SlideshowEditActivity.class);
intent.setData(dataUri);
startActivityForResult(intent, REQUEST_CODE_CREATE_SLIDESHOW);
}
private String getDeafaultGroupName(int groupNameId){
String groupName = "";
switch(groupNameId){
case GROUP_NAME_STUDENT:
// ContentValues values1 = new ContentValues();
groupName = this.getString(R.string.group_name_student);
// values1.put("divided_name", groupName);
// this.getContentResolver().update(DIVIDED_GROUP_URI, values1, "_id=" + groupNameId, null);
break;
case GROUP_NAME_FRIEND:
// ContentValues values2 = new ContentValues();
groupName = this.getString(R.string.group_name_friend);
// values2.put("divided_name", groupName);
// this.getContentResolver().update(DIVIDED_GROUP_URI, values2, "_id=" + groupNameId, null);
break;
case GROUP_NAME_FAMILY:
// ContentValues values3 = new ContentValues();
groupName = this.getString(R.string.group_name_family);
// values3.put("divided_name", groupName);
// this.getContentResolver().update(DIVIDED_GROUP_URI, values3, "_id=" + groupNameId, null);
break;
case GROUP_NAME_COLLEAGUE:
// ContentValues values4 = new ContentValues();
groupName = this.getString(R.string.group_name_colleague);
// values4.put("divided_name", groupName);
// this.getContentResolver().update(DIVIDED_GROUP_URI, values4, "_id=" + groupNameId, null);
break;
default:
break;
}
return groupName;
}
private Handler mAttachmentEditorHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AttachmentEditor.MSG_EDIT_SLIDESHOW: {
editSlideshow();
break;
}
case AttachmentEditor.MSG_SEND_SLIDESHOW: {
if (isPreparedForSending()) {
ComposeMessageActivity.this.confirmSendMessageIfNeeded();
}
break;
}
case AttachmentEditor.MSG_VIEW_IMAGE:
case AttachmentEditor.MSG_PLAY_VIDEO:
case AttachmentEditor.MSG_PLAY_AUDIO:
case AttachmentEditor.MSG_PLAY_SLIDESHOW:
MessageUtils.viewMmsMessageAttachment(ComposeMessageActivity.this,
mWorkingMessage);
break;
case AttachmentEditor.MSG_REPLACE_IMAGE:
case AttachmentEditor.MSG_REPLACE_VIDEO:
case AttachmentEditor.MSG_REPLACE_AUDIO:
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 begin =====
IS_APPEND_MEDIA = false;
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 end =====
showAddAttachmentDialog(true);
break;
case AttachmentEditor.MSG_REMOVE_ATTACHMENT:
//CR NEWMS00107285 Modify Start
//yuechao fix for bug 10371 start
if(!isSubjectEditorVisible() || mSubjectTextEditor.length() == 0){
showSubjectEditor(false);
mWorkingMessage.setSubject(null, true);
}
//yuechao fix for bug 10371 end
//CR NEWMS00107285 Modify End
mWorkingMessage.setAttachment(WorkingMessage.TEXT, null, false);
break;
// ======fixed CR<NEWMS00120798> by luning at 2011.11.09 begin======
case AttachmentEditor.MSG_VIEW_VCARD:
VcardModel vcardmodel = mWorkingMessage.getSlideshow().mVcards
.get(0);
String detail = vcardmodel.getDetail();
String name = vcardmodel.getSrc();
if (null == detail || detail.length() <= 0) {
detail = getString(R.string.cannot_get_details);
}
new AlertDialog.Builder(ComposeMessageActivity.this).setIcon(
R.drawable.vcf).setTitle(name).setMessage(detail)
.setPositiveButton(getString(R.string.yes), null)
.show();
break;
// ======fixed CR<NEWMS00120798> by luning at 2011.11.09 end======
default:
break;
}
}
};
private Handler mMessageListItemHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String type;
switch (msg.what) {
case MessageListItem.MSG_LIST_EDIT_MMS:
type = "mms";
break;
case MessageListItem.MSG_LIST_EDIT_SMS:
type = "sms";
break;
default:
Log.w(TAG, "Unknown message: " + msg.what);
return;
}
MessageItem msgItem = getMessageItem(type, (Long) msg.obj, false);
if (msgItem != null) {
editMessageItem(msgItem);
drawBottomPanel();
}
}
};
private Handler mMessageOperationHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg == null){
return;
}
switch (msg.what) {
case MENU_COPY_MESSAGE_TO_SIM:
Log.d(TAG, "Do copy message to sim");
Bundle bun = msg.getData();
if(bun != null){
String type = bun.getString("type");
Long msgId = bun.getLong("msgId", -1);
int phoneId = bun.getInt("PhoneId", -1);
Log.i(TAG,"Do copy message to sim type is"+type);
Log.i(TAG,"Do copy message to sim msgId is"+msgId);
Log.i(TAG,"Do copy message to sim phoneId is"+phoneId);
MessageItem msgItem = getMessageItem(type, msgId, true);
if(msgItem != null){
copyMessageToSim(msgItem,phoneId);
}else{
Log.i(TAG,"Do copy message to sim getMessageItem(type, msgId, true) is null");
}
}else{
Log.i(TAG,"Do copy message to sim msg.getData() is null");
}
break;
default:
Log.w(TAG, "Unknown message: " + msg.what);
return;
}
}
};
private OnKeyListener mSubjectKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return false;
}
// When the subject editor is empty, press "DEL" to hide the input field.
if ((keyCode == KeyEvent.KEYCODE_DEL) && (mSubjectTextEditor.length() == 0)) {
showSubjectEditor(false);
mWorkingMessage.setSubject(null, true);
return true;
}
return false;
}
};
/**
* Return the messageItem associated with the type ("mms" or "sms") and message id.
* @param type Type of the message: "mms" or "sms"
* @param msgId Message id of the message. This is the _id of the sms or pdu row and is
* stored in the MessageItem
* @param createFromCursorIfNotInCache true if the item is not found in the MessageListAdapter's
* cache and the code can create a new MessageItem based on the position of the current cursor.
* If false, the function returns null if the MessageItem isn't in the cache.
* @return MessageItem or null if not found and createFromCursorIfNotInCache is false
*/
private MessageItem getMessageItem(String type, long msgId,
boolean createFromCursorIfNotInCache) {
return mMsgListAdapter.getCachedMessageItem(type, msgId,
createFromCursorIfNotInCache ? mMsgListAdapter.getCursor() : null);
}
private boolean isCursorValid() {
// Check whether the cursor is valid or not.
Cursor cursor = mMsgListAdapter.getCursor();
if (cursor.isClosed() || cursor.isBeforeFirst() || cursor.isAfterLast()) {
Log.e(TAG, "Bad cursor.", new RuntimeException());
return false;
}
return true;
}
private void resetCounter() {
mTextCounter.setText("");
mTextCounter.setVisibility(View.GONE);
}
//2012-02-14 fix for bug 10574
private void reCalcSmsCounter(CharSequence text){
WorkingMessage workingMessage = mWorkingMessage;
int[] params = SmsMessage.calculateLength(text, false);
/* SmsMessage.calculateLength returns an int[4] with:
* int[0] being the number of SMS's required,
* int[1] the number of code units used,
* int[2] is the number of code units remaining until the next message.
* int[3] is the encoding type that should be used for the message.
*/
int msgCount = params[0];
int remainingInCurrentMessage = params[2];
boolean showCounter = true;
if (showCounter) {
// Update the remaining characters and number of messages required.
String counterText = msgCount > 1 ? remainingInCurrentMessage + "/" + msgCount
: String.valueOf(remainingInCurrentMessage)+ "/" + 1;
mTextCounter.setText(counterText);
//mTitleRight.setText(counterText);
mTextCounter.setVisibility(View.VISIBLE);
} else {
mTextCounter.setVisibility(View.GONE);
}
}
private void updateCounter(CharSequence text, int start, int before, int count) {
WorkingMessage workingMessage = mWorkingMessage;
// if (workingMessage.requiresMms()) {
// // If we're not removing text (i.e. no chance of converting back to SMS
// // because of this change) and we're in MMS mode, just bail out since we
// // then won't have to calculate the length unnecessarily.
// final boolean textRemoved = (before > count);
// if (!textRemoved) {
// setSendButtonText(workingMessage.requiresMms());
// return;
// }
// }
int[] params = SmsMessage.calculateLength(text, false);
/* SmsMessage.calculateLength returns an int[4] with:
* int[0] being the number of SMS's required,
* int[1] the number of code units used,
* int[2] is the number of code units remaining until the next message.
* int[3] is the encoding type that should be used for the message.
*/
int msgCount = params[0];
if (workingMessage.requiresMms()) {
// If we're not removing text (i.e. no chance of converting back to SMS
// because of this change) and we're in MMS mode, just bail out since we
// then won't have to calculate the length unnecessarily.
final boolean textRemoved = (before > count);
if (!textRemoved) {
setSendButtonText(workingMessage.requiresMms());
//fix for bug 10574 start phone02
if(msgCount > MmsConfig.getSmsToMmsTextThreshold()){
mWorkingMessage.setLengthRequiresMms(
msgCount > MmsConfig.getSmsToMmsTextThreshold(), true);
}
//fix for bug 10574 phone02 end
return;
}
}
// === modify by luning for NEWMS00107396 at 11-09-02 begin ===
if(msgCount >=11 && !workingMessage.requiresMms()/*fixed CR<NEWMS00148018> by luning at 2011.12.21 */){
/* modify by luning for HUAWEI bug at 2011.12.27 begin */
SmsManager smsManager = SmsManager.getDefault();
ArrayList<String> messages = smsManager.divideMessage(text.toString());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(messages.get(i));
}
mTextEditor.setText(sb.subSequence(0, sb.length()));
// mTextEditor.setText(text.subSequence(0, start));
/* modify by luning for HUAWEI bug at 2011.12.27 end */
Selection.setSelection(mTextEditor.getText(), mTextEditor
.length());
return;
}
// === modify by luning for NEWMS00107396 at 11-09-02 end ===
int remainingInCurrentMessage = params[2];
//update by spreadst_lishengjie start 2012-1-30 : fix bug9176
//if (!MmsConfig.getMultipartSmsEnabled()) {
mWorkingMessage.setLengthRequiresMms(
msgCount > MmsConfig.getSmsToMmsTextThreshold(), true);
//}
//update by spreadst_lishengjie end 2012-1-30
// Show the counter only if:
// - We are not in MMS mode
// - We are going to send more than one message OR we are getting close
//boolean showCounter = false;
boolean showCounter = true;
//===== fixed CR<NEWMS00134916> by luning at 11-10-28 begin =====
// if (!workingMessage.requiresMms() &&
// (msgCount > 1 ||
// remainingInCurrentMessage <= CHARS_REMAINING_BEFORE_COUNTER_SHOWN)) {
// showCounter = true;
// }
if(workingMessage.requiresMms()){
showCounter = false;
}
//===== fixed CR<NEWMS00134916> by luning at 11-10-28 begin =====
setSendButtonText(workingMessage.requiresMms());
if (showCounter) {
// Update the remaining characters and number of messages required.
String counterText = msgCount > 1 ? remainingInCurrentMessage + "/" + msgCount
: String.valueOf(remainingInCurrentMessage)+ "/" + 1;
mTextCounter.setText(counterText);
//mTitleRight.setText(counterText);
mTextCounter.setVisibility(View.VISIBLE);
} else {
mTextCounter.setVisibility(View.GONE);
}
}
@Override
public void startActivityForResult(Intent intent, int requestCode)
{
// requestCode >= 0 means the activity in question is a sub-activity.
if (requestCode >= 0) {
mWaitingForSubActivity = true;
}
super.startActivityForResult(intent, requestCode);
}
private void toastConvertInfo(boolean toMms) {
final int resId = toMms ? R.string.converting_to_picture_message
: R.string.converting_to_text_message;
Toast.makeText(this, resId, Toast.LENGTH_SHORT).show();
}
private class DeleteMessageListener implements OnClickListener {
private final Uri mDeleteUri;
private final boolean mDeleteLocked;
public DeleteMessageListener(Uri uri, boolean deleteLocked) {
mDeleteUri = uri;
mDeleteLocked = deleteLocked;
}
public DeleteMessageListener(long msgId, String type, boolean deleteLocked) {
if ("mms".equals(type)) {
mDeleteUri = ContentUris.withAppendedId(Mms.CONTENT_URI, msgId);
} else {
mDeleteUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId);
}
mDeleteLocked = deleteLocked;
}
public void onClick(DialogInterface dialog, int whichButton) {
mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN,
null, mDeleteUri, mDeleteLocked ? null : "locked=0", null);
dialog.dismiss();
}
}
private class DiscardDraftListener implements OnClickListener {
public void onClick(DialogInterface dialog, int whichButton) {
//modify by liguxiang 10-11-11 for NEWM00129822 begin
if(whichButton == dialog.BUTTON_POSITIVE){
mWorkingMessage.discard();
finish();
}else if(whichButton == dialog.BUTTON_NEUTRAL){
mToastForDraftSave = true;
saveDraft();
finish();
}
//modify by liguxiang 10-11-11 for NEWM00129822 end
// mWorkingMessage.discard();
// dialog.dismiss();
// finish();
}
}
private class SendIgnoreInvalidRecipientListener implements OnClickListener {
public void onClick(DialogInterface dialog, int whichButton) {
sendMessage(true);
dialog.dismiss();
}
}
private class CancelSendingListener implements OnClickListener {
public void onClick(DialogInterface dialog, int whichButton) {
if (isRecipientsEditorVisible()) {
mRecipientsEditor.requestFocus();
}
dialog.dismiss();
}
}
private void confirmSendMessageIfNeeded() {
boolean isMms = mWorkingMessage.requiresMms();
//20120204 start
if(isMms){
//check the mms size beyond the limit,when send the mms message
SlideshowModel slideshow = mWorkingMessage.getSlideshow();
if(slideshow != null){
long mmssize = slideshow.getTotalMsgSizeWithAllHead();
Log.d(TAG, "mmssize:"+mmssize);
if(DownloadManager.getInstance().checkMmsSizeLimit(mmssize)){
runOnUiThread(new Runnable() {
public void run() {
String title = ComposeMessageActivity.this.getResources().getString(R.string.exceed_message_size_limitation);
String message = ComposeMessageActivity.this.getResources().getString(R.string.exceed_message_size_limitation);
MessageUtils.showErrorDialog(ComposeMessageActivity.this, title, message);
}
});
return;
}
}
}
//20120204 start
if (!isRecipientsEditorVisible()) {
sendMessage(true);
return;
}
if (mRecipientsEditor.hasInvalidRecipient(isMms)) {
if (mRecipientsEditor.hasValidRecipient(isMms)) {
String title = getResourcesString(R.string.has_invalid_recipient,
mRecipientsEditor.formatInvalidNumbers(isMms));
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(title)
.setMessage(R.string.invalid_recipient_message)
.setPositiveButton(R.string.try_to_send,
new SendIgnoreInvalidRecipientListener())
.setNegativeButton(R.string.no, new CancelSendingListener())
.show();
} else {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.cannot_send_message)
.setMessage(R.string.cannot_send_message_reason)
.setPositiveButton(R.string.yes, new CancelSendingListener())
.show();
}
} else {
sendMessage(true);
}
if(MessageUtils.isMSMS){
//TODO
}else{
if(isSomeSmsUnReady()){
Toast.makeText(this, this.getResources().getString(R.string.sim_no_ready),
Toast.LENGTH_LONG).show();
}
}
}
public boolean isSomeSmsUnReady() {
if(TelephonyManager.getPhoneCount() <= 1) {
if(!mSmsReady[0]) {
return true;
} else {
return false;
}
} else {
if(mWorkingMessage != null) {
if(!mSmsReady[mWorkingMessage.getPhoneId()]) {
return true;
} else {
return false;
}
} else {
if(!mSmsReady[0] && !mSmsReady[1]) {
return true;
} else {
return false;
}
}
}
}
private TextWatcher mRecipientsWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// This is a workaround for bug 1609057. Since onUserInteraction() is
// not called when the user touches the soft keyboard, we pretend it was
// called when textfields changes. This should be removed when the bug
// is fixed.
onUserInteraction();
}
public void afterTextChanged(Editable s) {
// Bug 1474782 describes a situation in which we send to
// the wrong recipient. We have been unable to reproduce this,
// but the best theory we have so far is that the contents of
// mRecipientList somehow become stale when entering
// ComposeMessageActivity via onNewIntent(). This assertion is
// meant to catch one possible path to that, of a non-visible
// mRecipientsEditor having its TextWatcher fire and refreshing
// mRecipientList with its stale contents.
if (!isRecipientsEditorVisible()) {
IllegalStateException e = new IllegalStateException(
"afterTextChanged called with invisible mRecipientsEditor");
// Make sure the crash is uploaded to the service so we
// can see if this is happening in the field.
Log.w(TAG,
"RecipientsWatcher: afterTextChanged called with invisible mRecipientsEditor");
return;
}
mWorkingMessage.setWorkingRecipients(mRecipientsEditor.getNumbers());
mWorkingMessage.setHasEmail(mRecipientsEditor.containsEmail(), true);
checkForTooManyRecipients();
// Walk backwards in the text box, skipping spaces. If the last
// character is a comma, update the title bar.
for (int pos = s.length() - 1; pos >= 0; pos--) {
char c = s.charAt(pos);
if (c == ' ')
continue;
if (c == ',') {
updateTitle(mConversation.getRecipients());
}
break;
}
// fix bug 13720 start
if (s.length() == 0) {
mConversation.setRecipients(new ContactList());
updateTitle(mConversation.getRecipients());
}
// fix bug 13720 end
// If we have gone to zero recipients, disable send button.
updateSendButtonState();
}
};
private void checkForTooManyRecipients() {
final int recipientLimit = MmsConfig.getRecipientLimit();
if (recipientLimit != Integer.MAX_VALUE) {
final int recipientCount = recipientCount();
boolean tooMany = recipientCount > recipientLimit;
if (recipientCount != mLastRecipientCount) {
// Don't warn the user on every character they type when they're over the limit,
// only when the actual # of recipients changes.
mLastRecipientCount = recipientCount;
if (tooMany) {
String tooManyMsg = getString(R.string.too_many_recipients, recipientCount,
recipientLimit);
Toast.makeText(ComposeMessageActivity.this,
tooManyMsg, Toast.LENGTH_LONG).show();
}
}
}
}
private OnCreateContextMenuListener mRecipientsMenuCreateListener =
new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if (menuInfo != null) {
Contact c = ((RecipientContextMenuInfo) menuInfo).recipient;
RecipientsMenuClickListener l = new RecipientsMenuClickListener(c);
menu.setHeaderTitle(c.getName());
if (c.existsInDatabase()) {
menu.add(0, MENU_VIEW_CONTACT, 0, R.string.menu_view_contact)
.setOnMenuItemClickListener(l);
} else if (canAddToContacts(c)){
menu.add(0, MENU_ADD_TO_CONTACTS, 0, R.string.menu_add_to_contacts)
.setOnMenuItemClickListener(l);
}
}
}
};
private class RecipientsMenuClickListener implements MenuItem.OnMenuItemClickListener {
private final Contact mRecipient;
RecipientsMenuClickListener(Contact recipient) {
mRecipient = recipient;
}
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
// Context menu handlers for the recipients editor.
case MENU_VIEW_CONTACT: {
Uri contactUri = mRecipient.getUri();
Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivityForResult(intent, 0);
return true;
}
case MENU_ADD_TO_CONTACTS: {
mAddContactIntent = ConversationList.createAddContactIntent(
mRecipient.getNumber());
ComposeMessageActivity.this.startActivityForResult(mAddContactIntent,
REQUEST_CODE_ADD_CONTACT);
return true;
}
}
return false;
}
}
private boolean canAddToContacts(Contact contact) {
// There are some kind of automated messages, like STK messages, that we don't want
// to add to contacts. These names begin with special characters, like, "*Info".
final String name = contact.getName();
if (!TextUtils.isEmpty(contact.getNumber())) {
char c = contact.getNumber().charAt(0);
if (isSpecialChar(c)) {
return false;
}
}
if (!TextUtils.isEmpty(name)) {
char c = name.charAt(0);
if (isSpecialChar(c)) {
return false;
}
}
if (!(Mms.isEmailAddress(name) || Mms.isPhoneNumber(name) ||
MessageUtils.isLocalNumber(contact.getNumber()))) { // Handle "Me"
return false;
}
return true;
}
private boolean isSpecialChar(char c) {
return c == '*' || c == '%' || c == '$';
}
private void addPositionBasedMenuItems(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) menuInfo;
} catch (ClassCastException e) {
Log.e(TAG, "bad menuInfo");
return;
}
final int position = info.position;
addUriSpecificMenuItems(menu, v, position);
}
private Uri getSelectedUriFromMessageList(ListView listView, int position) {
// If the context menu was opened over a uri, get that uri.
MessageListItem msglistItem = (MessageListItem) listView.getChildAt(position);
if (msglistItem == null) {
// FIXME: Should get the correct view. No such interface in ListView currently
// to get the view by position. The ListView.getChildAt(position) cannot
// get correct view since the list doesn't create one child for each item.
// And if setSelection(position) then getSelectedView(),
// cannot get corrent view when in touch mode.
return null;
}
TextView textView;
CharSequence text = null;
int selStart = -1;
int selEnd = -1;
//check if message sender is selected
textView = (TextView) msglistItem.findViewById(R.id.text_view);
if (textView != null) {
text = textView.getText();
selStart = textView.getSelectionStart();
selEnd = textView.getSelectionEnd();
}
if (selStart == -1) {
//sender is not being selected, it may be within the message body
textView = (TextView) msglistItem.findViewById(R.id.body_text_view);
if (textView != null) {
text = textView.getText();
selStart = textView.getSelectionStart();
selEnd = textView.getSelectionEnd();
}
}
// Check that some text is actually selected, rather than the cursor
// just being placed within the TextView.
if (selStart != selEnd) {
int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd);
URLSpan[] urls = ((Spanned) text).getSpans(min, max,
URLSpan.class);
if (urls.length == 1) {
return Uri.parse(urls[0].getURL());
}
}
//no uri was selected
return null;
}
private void addUriSpecificMenuItems(ContextMenu menu, View v, int position) {
Uri uri = getSelectedUriFromMessageList((ListView) v, position);
if (uri != null) {
Intent intent = new Intent(null, uri);
intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE);
menu.addIntentOptions(0, 0, 0,
new android.content.ComponentName(this, ComposeMessageActivity.class),
null, intent, 0, null);
}
}
private final void addCallAndContactMenuItems(
ContextMenu menu, MsgListMenuClickListener l, MessageItem msgItem) {
// Add all possible links in the address & message
StringBuilder textToSpannify = new StringBuilder();
if (msgItem.mBoxId == Mms.MESSAGE_BOX_INBOX) {
textToSpannify.append(msgItem.mAddress + ": ");
}
textToSpannify.append(msgItem.mBody);
SpannableString msg = new SpannableString(textToSpannify.toString());
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
// Linkify.addLinks(msg, Linkify.ALL);
Linkify.findLinks(msg, Linkify.ALL);
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
ArrayList<String> uris =
MessageUtils.extractUris(msg.getSpans(0, msg.length(), URLSpan.class));
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
ArrayList<String> webLinks = null;
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
while (uris.size() > 0) {
String uriString = uris.remove(0);
// Remove any dupes so they don't get added to the menu multiple
// times
while (uris.contains(uriString)) {
uris.remove(uriString);
}
int sep = uriString.indexOf(":");
String prefix = null;
if (sep >= 0) {
prefix = uriString.substring(0, sep);
uriString = uriString.substring(sep + 1);
}
boolean addToContacts = false;
if ("mailto".equalsIgnoreCase(prefix)) {
String sendEmailString = getString(R.string.menu_send_email)
.replace("%s", uriString);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri
.parse("mailto:" + uriString));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
menu.add(0, MENU_SEND_EMAIL, 0, sendEmailString)
.setOnMenuItemClickListener(l).setIntent(intent);
addToContacts = !haveEmailContact(uriString);
} else if ("tel".equalsIgnoreCase(prefix)) {
boolean bIsSendSMS = true;
String callBackString = getString(R.string.menu_call_back)
.replace("%s", uriString);
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
+ uriString));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
if (!msgItem.isWapPush) {
menu.add(0, MENU_CALL_BACK, 0, callBackString).setOnMenuItemClickListener(l)
.setIntent(intent);
}
if (TelephonyManager.MODEM_TYPE_TDSCDMA == TelephonyManager
.getDefault().getModemType()
&& !msgItem.isWapPush
&& SystemProperties.getBoolean("ro.device.support.vt",
true)) {
callBackString = getString(R.string.menu_videocall_back)
.replace("%s", uriString);
intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
+ uriString));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
menu.add(0, MENU_VIDEOCALL_BACK, 0, callBackString)
.setOnMenuItemClickListener(l).setIntent(
getVPIntent(intent));
}
if (bIsSendSMS) {
callBackString = getString(R.string.menu_send_sms).replace(
"%s", uriString);
intent = new Intent(Intent.ACTION_SENDTO, Uri
.parse("smsto:" + uriString));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
menu.add(0, MENU_SEND_SMS, 0, callBackString)
.setOnMenuItemClickListener(l).setIntent(intent);
}
addToContacts = !isNumberInContacts(uriString);
}
// ===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
else if ("http".equalsIgnoreCase(prefix)) {
if (null == webLinks) {
webLinks = new ArrayList<String>();
}
webLinks.add("http:" + uriString);
}
// ===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
if (addToContacts && !msgItem.isWapPush) {
Intent intent = ConversationList
.createAddContactIntent(uriString);
String addContactString = getString(
R.string.menu_add_address_to_contacts).replace("%s",
uriString);
menu.add(0, MENU_ADD_ADDRESS_TO_CONTACTS, 0, addContactString)
.setOnMenuItemClickListener(l).setIntent(intent);
}
}
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
if(null != webLinks && webLinks.size() > 0){
Intent intent = new Intent();
intent.putExtra("webLinks", webLinks);
menu.add(0, MENU_SAVE_BOOKMARK, 0, getString(R.string.save_to_bookmarks))
.setOnMenuItemClickListener(l).setIntent(intent);
}
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
}
private boolean haveEmailContact(String emailAddress) {
Cursor cursor = SqliteWrapper.query(this, getContentResolver(),
Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)),
new String[] { Contacts.DISPLAY_NAME }, null, null, null);
if (cursor != null) {
try {
while (cursor.moveToNext()) {
String name = cursor.getString(0);
if (!TextUtils.isEmpty(name)) {
return true;
}
}
} finally {
cursor.close();
}
}
return false;
}
private boolean isNumberInContacts(String phoneNumber) {
return Contact.get(phoneNumber, false).existsInDatabase();
}
private OnCreateContextMenuListener mMsgListMenuCreateListener =
new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
Cursor cursor = mMsgListAdapter.getCursor();
String type = cursor.getString(COLUMN_MSG_TYPE);
long msgId = cursor.getLong(COLUMN_ID);
addPositionBasedMenuItems(menu, v, menuInfo);
MessageItem msgItem = mMsgListAdapter.getCachedMessageItem(type, msgId, cursor);
MessageListItem mli = (MessageListItem)((AdapterView.AdapterContextMenuInfo)menuInfo).targetView;
if (msgItem == null) {
Log.e(TAG, "Cannot load message item for type = " + type
+ ", msgId = " + msgId);
return;
}
menu.setHeaderTitle(R.string.message_options);
MsgListMenuClickListener l = new MsgListMenuClickListener();
if (msgItem.mLocked) {
menu.add(0, MENU_UNLOCK_MESSAGE, 0, R.string.menu_unlock)
.setOnMenuItemClickListener(l);
} else {
menu.add(0, MENU_LOCK_MESSAGE, 0, R.string.menu_lock)
.setOnMenuItemClickListener(l);
}
if (msgItem.isMms()) {
switch (msgItem.mBoxId) {
case Mms.MESSAGE_BOX_INBOX:
break;
case Mms.MESSAGE_BOX_OUTBOX:
// Since we currently break outgoing messages to multiple
// recipients into one message per recipient, only allow
// editing a message for single-recipient conversations.
if (getRecipients().size() == 1) {
menu.add(0, MENU_EDIT_MESSAGE, 0, R.string.menu_edit)
.setOnMenuItemClickListener(l);
}
break;
}
switch (msgItem.mAttachmentType) {
case WorkingMessage.TEXT:
break;
case WorkingMessage.VIDEO:
case WorkingMessage.IMAGE:
if (haveSomethingToCopyToSDCard(msgItem.mMsgId)) {
menu.add(0, MENU_COPY_TO_SDCARD, 0, R.string.copy_to_sdcard)
.setOnMenuItemClickListener(l);
}
break;
case WorkingMessage.VCARD:
break;
case WorkingMessage.SLIDESHOW:
default:
menu.add(0, MENU_VIEW_SLIDESHOW, 0, R.string.view_slideshow)
.setOnMenuItemClickListener(l);
if (haveSomethingToCopyToSDCard(msgItem.mMsgId)) {
menu.add(0, MENU_COPY_TO_SDCARD, 0, R.string.copy_to_sdcard)
.setOnMenuItemClickListener(l);
}
if (haveSomethingToCopyToDrmProvider(msgItem.mMsgId)) {
menu.add(0, MENU_COPY_TO_DRM_PROVIDER, 0,
getDrmMimeMenuStringRsrc(msgItem.mMsgId))
.setOnMenuItemClickListener(l);
}
break;
}
messageBody = mli.getBodyTextView().getText().toString();
if (!TextUtils.isEmpty(messageBody)) {
menu.add(0, MENU_COPY_MMS_MESSAGE_TEXT, 0,
R.string.copy_message_text)
.setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(
MenuItem item) {
copyToClipboard(messageBody);
return true;
}
});
}
} else {
// Message type is sms. Only allow "edit" if the message has a single recipient
if (getRecipients().size() == 1 &&
(msgItem.mBoxId == Sms.MESSAGE_TYPE_OUTBOX ||
msgItem.mBoxId == Sms.MESSAGE_TYPE_FAILED)) {
menu.add(0, MENU_EDIT_MESSAGE, 0, R.string.menu_edit)
.setOnMenuItemClickListener(l);
}
}
addCallAndContactMenuItems(menu, l, msgItem);
// Forward is not available for undownloaded messages.
if (msgItem.isDownloaded()) {
menu.add(0, MENU_FORWARD_MESSAGE, 0, R.string.menu_forward)
.setOnMenuItemClickListener(l);
}
// resent message when sms send failed
if (msgItem.isFailedMessage() ) {//&& msgItem.isSms()
menu.add(0, MENU_RESEND_MESSAGE, 0, R.string.menu_resend)
.setOnMenuItemClickListener(l);
}
// It is unclear what would make most sense for copying an MMS message
// to the clipboard, so we currently do SMS only.
if (msgItem.isSms()) {
menu.add(0, MENU_COPY_MESSAGE_TEXT, 0, R.string.copy_message_text)
.setOnMenuItemClickListener(l);
menu.add(0, MENU_COPY_MESSAGE_TO_SIM, 0, R.string.move_message_to_sim_text)
.setOnMenuItemClickListener(l);
}
menu.add(0, MENU_VIEW_MESSAGE_DETAILS, 0, R.string.view_message_details)
.setOnMenuItemClickListener(l);
menu.add(0, MENU_DELETE_MESSAGE, 0, R.string.delete_message)
.setOnMenuItemClickListener(l);
if (msgItem.mDeliveryStatus != MessageItem.DeliveryStatus.NONE || msgItem.mReadReport) {
menu.add(0, MENU_DELIVERY_REPORT, 0, R.string.view_delivery_report)
.setOnMenuItemClickListener(l);
}
}
};
private void editMessageItem(MessageItem msgItem) {
if ("sms".equals(msgItem.mType)) {
editSmsMessageItem(msgItem);
} else {
editMmsMessageItem(msgItem);
}
if (msgItem.isFailedMessage() && mMsgListAdapter.getCount() <= 1) {
// For messages with bad addresses, let the user re-edit the recipients.
initRecipientsEditor();
}
}
private void editSmsMessageItem(MessageItem msgItem) {
// When the message being edited is the only message in the conversation, the delete
// below does something subtle. The trigger "delete_obsolete_threads_pdu" sees that a
// thread contains no messages and silently deletes the thread. Meanwhile, the mConversation
// object still holds onto the old thread_id and code thinks there's a backing thread in
// the DB when it really has been deleted. Here we try and notice that situation and
// clear out the thread_id. Later on, when Conversation.ensureThreadId() is called, we'll
// create a new thread if necessary.
synchronized(mConversation) {
if (mConversation.getMessageCount() <= 1) {
mConversation.clearThreadId();
}
}
// Delete the old undelivered SMS and load its content.
Uri uri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgItem.mMsgId);
//fixed bug17720 start
if (outboxEditMsgFlg) {
SqliteWrapper.delete(ComposeMessageActivity.this, mContentResolver, uri, null, null);
} else {
/*fixed CR<NEWMS00147583> by luning at 2011.12.07 begin*/
if (msgItem.isFailedMessage()) {
ContentValues values = new ContentValues(1);
values.put(Sms.TYPE, Sms.MESSAGE_TYPE_DRAFT);
SqliteWrapper.update(ComposeMessageActivity.this, mContentResolver, uri, values, null,
null);
}
/*fixed CR<NEWMS00147583> by luning at 2011.12.07 end*/
else {
SqliteWrapper.delete(ComposeMessageActivity.this, mContentResolver, uri, null, null);
}
}
//fixed bug17720 end
mWorkingMessage.setText(msgItem.mBody);
}
private void editMmsMessageItem(MessageItem msgItem) {
// Discard the current message in progress.
mWorkingMessage.discard();
// Load the selected message in as the working message.
mWorkingMessage = WorkingMessage.load(this, msgItem.mMessageUri, false);
mWorkingMessage.setConversation(mConversation);
mAttachmentEditor.update(mWorkingMessage);
drawTopPanel();
// WorkingMessage.load() above only loads the slideshow. Set the
// subject here because we already know what it is and avoid doing
// another DB lookup in load() just to get it.
mWorkingMessage.setSubject(msgItem.mSubject, false);
if (mWorkingMessage.hasSubject()) {
showSubjectEditor(true);
}
}
public void copyToClipboard(String str) {
ClipboardManager clip =
(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
clip.setText(str);
}
private void resendMessage(MessageItem msgItem) {
Uri uri;
if ("sms".equals(msgItem.mType)) {
uri = Sms.CONTENT_URI;
final Uri resendUri = ContentUris.withAppendedId(uri, msgItem.mMsgId);
final ContentValues values = new ContentValues(1);
values.put(Sms.TYPE, Sms.MESSAGE_TYPE_QUEUED);
values.put(Sms.DATE, System.currentTimeMillis());
getContentResolver().update(resendUri, values, null, null);
this.getApplicationContext().sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
null,
this.getApplicationContext(),
SmsReceiver.class));
} else {
// Now update the pending_msgs table with an error for that new item.
ContentValues values = new ContentValues(4);
values.put(PendingMessages.ERROR_TYPE, MmsSms.NO_ERROR);
values.put(PendingMessages.ERROR_CODE, 0);
values.put(PendingMessages.RETRY_INDEX, 0);
values.put(PendingMessages.DUE_TIME, 0);
long msgId = ContentUris.parseId(msgItem.mMessageUri);
SqliteWrapper.update(this, mContentResolver,
PendingMessages.CONTENT_URI,
values, PendingMessages._ID + "=" + msgId, null);
// Start MMS transaction service
SendingProgressTokenManager.put(ContentUris.parseId(msgItem.mMessageUri), mConversation.ensureThreadId());
this.startService(new Intent(this, TransactionService.class));
}
}
private void resendMessage(MessageItem msgItem,int phoneId) {
Uri uri;
if ("sms".equals(msgItem.mType)) {
uri = Sms.CONTENT_URI;
final Uri resendUri = ContentUris.withAppendedId(uri, msgItem.mMsgId);
final ContentValues values = new ContentValues(1);
values.put(Sms.TYPE, Sms.MESSAGE_TYPE_QUEUED);
values.put(Sms.DATE, System.currentTimeMillis());
getContentResolver().update(resendUri, values, null, null);
this.getApplicationContext().sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
null,
this.getApplicationContext(),
SmsReceiver.class));
} else {
// Now update the pending_msgs table with an error for that new item.
ContentValues values = new ContentValues(4);
values.put(PendingMessages.ERROR_TYPE, MmsSms.NO_ERROR);
values.put(PendingMessages.ERROR_CODE, 0);
values.put(PendingMessages.RETRY_INDEX, 0);
values.put(PendingMessages.DUE_TIME, 0);
long msgId = ContentUris.parseId(msgItem.mMessageUri);
SqliteWrapper.update(this, mContentResolver,
PendingMessages.CONTENT_URI,
values, PendingMessages.MSG_ID + "=" + msgId, null);
// Start MMS transaction service
SendingProgressTokenManager.put(ContentUris.parseId(msgItem.mMessageUri), mConversation.ensureThreadId());
//this.startService(new Intent(this, TransactionService.class));
if (MessageUtils.isMSMS){
Log.i(TAG,"mPhoneId is"+phoneId);
this.startService(new Intent(this, TransactionServiceHelper
.getTransactionServiceClass(phoneId)));
} else {
this.startService(new Intent(this, TransactionService.class));
}
}
}
private void forwardMessage(MessageItem msgItem) {
Intent intent = createIntent(this, 0);
intent.putExtra("exit_on_sent", true);
intent.putExtra("forwarded_message", true);
intent.putExtra("sender_number", msgItem.mAddress);
if (msgItem.mType.equals("sms")) {
intent.putExtra("sms_body", msgItem.mBody);
} else {
SendReq sendReq = new SendReq();
String subject = getString(R.string.forward_prefix);
if (msgItem.mSubject != null) {
subject += msgItem.mSubject;
}
sendReq.setSubject(new EncodedStringValue(subject));
sendReq.setBody(msgItem.mSlideshow.makeCopy(
ComposeMessageActivity.this));
Uri uri = null;
try {
PduPersister persister = PduPersister.getPduPersister(this);
// Copy the parts of the message here.
uri = persister.persist(sendReq, Mms.Draft.CONTENT_URI);
} catch (MmsException e) {
Log.e(TAG, "Failed to copy message: " + msgItem.mMessageUri, e);
Toast.makeText(ComposeMessageActivity.this,
R.string.cannot_save_message, Toast.LENGTH_SHORT).show();
return;
}
intent.putExtra("msg_uri", uri);
intent.putExtra("subject", subject);
}
// ForwardMessageActivity is simply an alias in the manifest for ComposeMessageActivity.
// We have to make an alias because ComposeMessageActivity launch flags specify
// singleTop. When we forward a message, we want to start a separate ComposeMessageActivity.
// The only way to do that is to override the singleTop flag, which is impossible to do
// in code. By creating an alias to the activity, without the singleTop flag, we can
// launch a separate ComposeMessageActivity to edit the forward message.
intent.setClassName(this, "com.android.mms.ui.ForwardMessageActivity");
startActivity(intent);
}
private void copyMessageToSim(MessageItem msgItem,int phoneId) {
boolean result = false;
boolean isOutgoing = false;
String timeString = null;
String bcdtimeString = null;
if (msgItem.mType.equals("sms")) {
SmsManager smsManager = SmsManager.getDefault(phoneId);
ArrayList<String> messages = null;
messages = smsManager.divideMessage(msgItem.mBody);
//boolean isOutgoing = msgItem.isOutgoingMessage();
if (msgItem.getBoxId() == Sms.MESSAGE_TYPE_SENT){
isOutgoing = true;
}
Log.d(TAG, "[cmgw]isOutgoing =" + isOutgoing);
//if (!isOutgoing) {
Time t = new Time();
t.set(msgItem.mDate);
timeString = t.format("%g%m%d%H%M%S");
Log.d(TAG, "[cmgw]timeString =" + timeString);
// byte[] timebcd = PhoneNumberUtils.numberToCalledPartyBCD(timeString);
// Log.d(TAG, "[cmgw]bcdlen ="+timebcd.length+" timelen =" + timeString.length());
// if (timebcd.length > timeString.length()/2) {
// int dataIndex = 1;
// byte[] data = new byte[timebcd.length - dataIndex];
// System.arraycopy(timebcd, dataIndex, data, 0, data.length);
// bcdtimeString = IccUtils.bytesToHexString(data) + "00";
// } else {
// bcdtimeString = IccUtils.bytesToHexString(timebcd) + "00";
// }
Log.d(TAG, "[cmgw]bcd timeString =" + bcdtimeString);
//}
byte[] timebcd = MessageUtils.GetSctsTime(t);
bcdtimeString = IccUtils.bytesToHexString(timebcd);
Log.d(TAG, "[cmgw]bcd timeString =" + bcdtimeString);
result = smsManager.saveMultipartTextMessage(msgItem.mAddress, messages, isOutgoing, bcdtimeString);
Log.d(TAG, "[cmgw]save result =" + result);
int resId = result ? R.string.copy_message_result_success :
R.string.copy_message_result_faile;
Toast.makeText(ComposeMessageActivity.this, resId, Toast.LENGTH_SHORT).show();
} else {
Log.d(TAG, "[cmgw]Not a sms, do nothing!!");
}
}
/**
* Context menu handlers for the message list view.
*/
private final class MsgListMenuClickListener implements MenuItem.OnMenuItemClickListener {
public boolean onMenuItemClick(MenuItem item) {
if (!isCursorValid()) {
return false;
}
Cursor cursor = mMsgListAdapter.getCursor();
String type = cursor.getString(COLUMN_MSG_TYPE);
int phoneId=cursor.getInt(COLUMN_SMS_PHONE_ID);
long msgId = cursor.getLong(COLUMN_ID);
MessageItem msgItem = getMessageItem(type, msgId, true);
Log.i(TAG,"onMenuItemClick phoneId is"+phoneId);
if (msgItem == null) {
return false;
}
switch (item.getItemId()) {
case MENU_EDIT_MESSAGE:
outboxEditMsgFlg = true;
editMessageItem(msgItem);
drawBottomPanel();
return true;
case MENU_COPY_MESSAGE_TEXT:
copyToClipboard(msgItem.mBody);
return true;
case MENU_COPY_MESSAGE_TO_SIM:
if(!mSmsReady[phoneId]){/* fixed CR<NEWMS00137946> by luning at 2011.11.15*/
Toast.makeText(ComposeMessageActivity.this, R.string.sim_no_ready,
Toast.LENGTH_LONG).show();
}else if (MessageUtils.isSimMemFull(phoneId)) {
Log.d(TAG, "sim memory full");
Toast.makeText(ComposeMessageActivity.this, R.string.sim_full_title,
Toast.LENGTH_SHORT).show();
} else {
Log.d(TAG, "Do copy message to sim");
Bundle bun = new Bundle();
bun.putLong("msgId", msgId);
bun.putString("type", type);
bun.putInt("PhoneId", phoneId);
Message msg = new Message();
msg.setData(bun);
msg.what = MENU_COPY_MESSAGE_TO_SIM;
if(mMessageOperationHandler != null){
mMessageOperationHandler.sendMessage(msg);
}
}
return true;
case MENU_FORWARD_MESSAGE:
forwardMessage(msgItem);
return true;
case MENU_RESEND_MESSAGE:
resendMessage(msgItem,phoneId);
return true;
case MENU_VIEW_SLIDESHOW:
MessageUtils.viewMmsMessageAttachment(ComposeMessageActivity.this,
ContentUris.withAppendedId(Mms.CONTENT_URI, msgId), null);
return true;
case MENU_VIEW_MESSAGE_DETAILS: {
String messageDetails = MessageUtils.getMessageDetails(
ComposeMessageActivity.this, cursor, msgItem.mMessageSize);
new AlertDialog.Builder(ComposeMessageActivity.this)
.setTitle(R.string.message_details_title)
.setMessage(messageDetails)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(true)
.show();
return true;
}
case MENU_DELETE_MESSAGE: {
DeleteMessageListener l = new DeleteMessageListener(
msgItem.mMessageUri, msgItem.mLocked);
confirmDeleteDialog(l, msgItem.mLocked);
return true;
}
case MENU_DELIVERY_REPORT:
showDeliveryReport(msgId, type);
return true;
case MENU_COPY_TO_SDCARD: {
String resStr;
if (copyMedia(msgId)) {
String dir = Environment.getExternalStorageDirectory() + "/"
+ Environment.DIRECTORY_DOWNLOADS + "/";
resStr = getString(R.string.copy_to_sdcard_success, dir);
} else {
resStr = getString(R.string.copy_to_sdcard_fail);
}
Toast.makeText(ComposeMessageActivity.this, resStr, Toast.LENGTH_SHORT).show();
return true;
}
case MENU_COPY_TO_DRM_PROVIDER: {
int resId = getDrmMimeSavedStringRsrc(msgId, copyToDrmProvider(msgId));
Toast.makeText(ComposeMessageActivity.this, resId, Toast.LENGTH_SHORT).show();
return true;
}
case MENU_LOCK_MESSAGE: {
lockMessage(msgItem, true);
return true;
}
case MENU_UNLOCK_MESSAGE: {
lockMessage(msgItem, false);
return true;
}
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 begin=====
case MENU_SAVE_BOOKMARK: {
Intent intent = item.getIntent();
if (null != intent) {
ArrayList<String> webLinks = (ArrayList<String>) intent
.getSerializableExtra("webLinks");
if (null != webLinks && webLinks.size() > 0) {
final CharSequence[] items = new CharSequence[webLinks.size()];
webLinks.toArray(items);
webLinks = null;
new AlertDialog.Builder(ComposeMessageActivity.this)
.setTitle(getString(R.string.save_to_bookmarks))
.setNegativeButton(getString(android.R.string.cancel), null).setItems(items,
new OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
Intent i = new Intent(
ACTION_SAVE_BOOKMARK);
i.putExtra("url", items[which]);
i.putExtra("retainIcon", false);
startActivity(i);
}
}).show();
}
}
return true;
}
//===== fixed CR<NEWMS00120677> by luning at 11-09-17 end=====
case MENU_ADD_ADDRESS_TO_CONTACTS: {
mAddContactIntent = item.getIntent();
ComposeMessageActivity.this.startActivityForResult(mAddContactIntent, REQUEST_CODE_ADD_CONTACT);
return true;
}
case MENU_SEND_SMS:
isLongPressSendFlg = true;
return false;
default:
return false;
}
}
}
private void lockMessage(MessageItem msgItem, boolean locked) {
Uri uri;
if ("sms".equals(msgItem.mType)) {
uri = Sms.CONTENT_URI;
} else {
uri = Mms.CONTENT_URI;
}
final Uri lockUri = ContentUris.withAppendedId(uri, msgItem.mMsgId);
final ContentValues values = new ContentValues(1);
values.put("locked", locked ? 1 : 0);
new Thread(new Runnable() {
public void run() {
getContentResolver().update(lockUri,
values, null, null);
}
}, "lockMessage").start();
}
/**
* Looks to see if there are any valid parts of the attachment that can be copied to a SD card.
* @param msgId
*/
private boolean haveSomethingToCopyToSDCard(long msgId) {
PduBody body = PduBodyCache.getPduBody(this,
ContentUris.withAppendedId(Mms.CONTENT_URI, msgId));
if (body == null) {
return false;
}
boolean result = false;
int partNum = body.getPartsNum();
for(int i = 0; i < partNum; i++) {
PduPart part = body.getPart(i);
String type = new String(part.getContentType());
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("[CMA] haveSomethingToCopyToSDCard: part[" + i + "] contentType=" + type);
}
if (ContentType.isImageType(type) || ContentType.isVideoType(type) ||
ContentType.isAudioType(type)) {
result = true;
break;
}
}
return result;
}
/**
* Looks to see if there are any drm'd parts of the attachment that can be copied to the
* DrmProvider. Right now we only support saving audio (e.g. ringtones).
* @param msgId
*/
private boolean haveSomethingToCopyToDrmProvider(long msgId) {
String mimeType = getDrmMimeType(msgId);
return isAudioMimeType(mimeType);
}
/**
* Simple cache to prevent having to load the same PduBody again and again for the same uri.
*/
private static class PduBodyCache {
private static PduBody mLastPduBody;
private static Uri mLastUri;
static public PduBody getPduBody(Context context, Uri contentUri) {
if (contentUri.equals(mLastUri)) {
return mLastPduBody;
}
try {
mLastPduBody = SlideshowModel.getPduBody(context, contentUri);
mLastUri = contentUri;
} catch (MmsException e) {
Log.e(TAG, e.getMessage(), e);
return null;
}
return mLastPduBody;
}
};
/**
* Copies media from an Mms to the DrmProvider
* @param msgId
*/
private boolean copyToDrmProvider(long msgId) {
boolean result = true;
PduBody body = PduBodyCache.getPduBody(this,
ContentUris.withAppendedId(Mms.CONTENT_URI, msgId));
if (body == null) {
return false;
}
int partNum = body.getPartsNum();
for(int i = 0; i < partNum; i++) {
PduPart part = body.getPart(i);
String type = new String(part.getContentType());
if (ContentType.isDrmType(type)) {
// All parts (but there's probably only a single one) have to be successful
// for a valid result.
result &= copyPartToDrmProvider(part);
}
}
return result;
}
private String mimeTypeOfDrmPart(PduPart part) {
Uri uri = part.getDataUri();
InputStream input = null;
try {
input = mContentResolver.openInputStream(uri);
if (input instanceof FileInputStream) {
FileInputStream fin = (FileInputStream) input;
DrmRawContent content = new DrmRawContent(fin, fin.available(),
DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING);
String mimeType = content.getContentType();
return mimeType;
}
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while opening or reading stream", e);
} catch (DrmException e) {
Log.e(TAG, "DrmException caught ", e);
} finally {
if (null != input) {
try {
input.close();
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while closing stream", e);
}
}
}
return null;
}
/**
* Returns the type of the first drm'd pdu part.
* @param msgId
*/
private String getDrmMimeType(long msgId) {
PduBody body = PduBodyCache.getPduBody(this,
ContentUris.withAppendedId(Mms.CONTENT_URI, msgId));
if (body == null) {
return null;
}
int partNum = body.getPartsNum();
for(int i = 0; i < partNum; i++) {
PduPart part = body.getPart(i);
String type = new String(part.getContentType());
if (ContentType.isDrmType(type)) {
return mimeTypeOfDrmPart(part);
}
}
return null;
}
private int getDrmMimeMenuStringRsrc(long msgId) {
String mimeType = getDrmMimeType(msgId);
if (isAudioMimeType(mimeType)) {
return R.string.save_ringtone;
}
return 0;
}
private int getDrmMimeSavedStringRsrc(long msgId, boolean success) {
String mimeType = getDrmMimeType(msgId);
if (isAudioMimeType(mimeType)) {
return success ? R.string.saved_ringtone : R.string.saved_ringtone_fail;
}
return 0;
}
private boolean isAudioMimeType(String mimeType) {
return mimeType != null && mimeType.startsWith("audio/");
}
private boolean isImageMimeType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/");
}
private boolean copyPartToDrmProvider(PduPart part) {
Uri uri = part.getDataUri();
InputStream input = null;
try {
input = mContentResolver.openInputStream(uri);
if (input instanceof FileInputStream) {
FileInputStream fin = (FileInputStream) input;
// Build a nice title
byte[] location = part.getName();
if (location == null) {
location = part.getFilename();
}
if (location == null) {
location = part.getContentLocation();
}
// Depending on the location, there may be an
// extension already on the name or not
String title = new String(location);
int index;
if ((index = title.indexOf(".")) == -1) {
String type = new String(part.getContentType());
} else {
title = title.substring(0, index);
}
// transfer the file to the DRM content provider
Intent item = DrmStore.addDrmFile(mContentResolver, fin, title);
if (item == null) {
Log.w(TAG, "unable to add file " + uri + " to DrmProvider");
return false;
}
}
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while opening or reading stream", e);
return false;
} finally {
if (null != input) {
try {
input.close();
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while closing stream", e);
return false;
}
}
}
return true;
}
/**
* Copies media from an Mms to the "download" directory on the SD card
* @param msgId
*/
private boolean copyMedia(long msgId) {
boolean result = true;
PduBody body = PduBodyCache.getPduBody(this,
ContentUris.withAppendedId(Mms.CONTENT_URI, msgId));
if (body == null) {
return false;
}
int partNum = body.getPartsNum();
for(int i = 0; i < partNum; i++) {
PduPart part = body.getPart(i);
String type = new String(part.getContentType());
if (ContentType.isImageType(type) || ContentType.isVideoType(type) ||
ContentType.isAudioType(type)) {
result &= copyPart(part, Long.toHexString(msgId)); // all parts have to be successful for a valid result.
}
}
return result;
}
private boolean copyPart(PduPart part, String fallback) {
Uri uri = part.getDataUri();
InputStream input = null;
FileOutputStream fout = null;
try {
input = mContentResolver.openInputStream(uri);
if (input instanceof FileInputStream) {
FileInputStream fin = (FileInputStream) input;
byte[] location = part.getName();
if (location == null) {
location = part.getFilename();
}
if (location == null) {
location = part.getContentLocation();
}
String fileName;
if (location == null) {
// Use fallback name.
fileName = fallback;
} else {
fileName = new String(location);
}
// Depending on the location, there may be an
// extension already on the name or not
String dir = Environment.getExternalStorageDirectory() + "/"
+ Environment.DIRECTORY_DOWNLOADS + "/";
String extension;
int index;
if ((index = fileName.indexOf(".")) == -1) {
String type = new String(part.getContentType());
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
} else {
extension = fileName.substring(index + 1, fileName.length());
fileName = fileName.substring(0, index);
}
File file = getUniqueDestination(dir + fileName, extension);
// make sure the path is valid and directories created for this file.
File parentFile = file.getParentFile();
if (!parentFile.exists() && !parentFile.mkdirs()) {
Log.e(TAG, "[MMS] copyPart: mkdirs for " + parentFile.getPath() + " failed!");
return false;
}
fout = new FileOutputStream(file);
byte[] buffer = new byte[8000];
int size = 0;
while ((size=fin.read(buffer)) != -1) {
fout.write(buffer, 0, size);
}
// Notify other applications listening to scanner events
// that a media file has been added to the sd card
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(file)));
}
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while opening or reading stream", e);
return false;
} finally {
if (null != input) {
try {
input.close();
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while closing stream", e);
return false;
}
}
if (null != fout) {
try {
fout.close();
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while closing stream", e);
return false;
}
}
}
return true;
}
private File getUniqueDestination(String base, String extension) {
File file = new File(base + "." + extension);
for (int i = 2; file.exists(); i++) {
file = new File(base + "_" + i + "." + extension);
}
return file;
}
private void showDeliveryReport(long messageId, String type) {
Intent intent = new Intent(this, DeliveryReportActivity.class);
intent.putExtra("message_id", messageId);
intent.putExtra("message_type", type);
startActivity(intent);
}
private IntentFilter mHttpProgressFilter = new IntentFilter(PROGRESS_STATUS_ACTION);
private BroadcastReceiver mHttpProgressReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (PROGRESS_STATUS_ACTION.equals(intent.getAction())) {
long token = intent.getLongExtra("token",
SendingProgressTokenManager.NO_TOKEN);
if (token != mConversation.getThreadId()) {
return;
}
int progress = intent.getIntExtra("progress", 0);
switch (progress) {
case PROGRESS_START:
setProgressBarVisibility(true);
break;
case PROGRESS_ABORT:
case PROGRESS_COMPLETE:
setProgressBarVisibility(false);
break;
default:
setProgress(100 * progress);
}
}
}
};
private static ContactList sEmptyContactList;
private ContactList getRecipients() {
// If the recipients editor is visible, the conversation has
// not really officially 'started' yet. Recipients will be set
// on the conversation once it has been saved or sent. In the
// meantime, let anyone who needs the recipient list think it
// is empty rather than giving them a stale one.
if (isRecipientsEditorVisible()) {
if (sEmptyContactList == null) {
sEmptyContactList = new ContactList();
}
return sEmptyContactList;
}
return mConversation.getRecipients();
}
private void updateTitle(ContactList list) {
String s;
switch (list.size()) {
case 0: {
String recipient = "";
if (mRecipientsEditor != null && mRecipientsEditor.getText() != null) {
recipient = mRecipientsEditor.getText().toString();
}
s = recipient;
break;
}
case 1: {
s = list.get(0).getNameAndNumber();
break;
}
default: {
// Handle multiple recipients
s = list.formatNames(", ");
break;
}
}
//yeezone:jinwei
if(FeatureSwitch.COMPOSE_MESSAGE_TIP_SUPPORT){
mTitleLeft.setText(s);
}else{
getWindow().setTitle(s);
}
mDebugRecipients = list.serialize();
// getWindow().setTitle(s);
}
// Get the recipients editor ready to be displayed onscreen.
private void initRecipientsEditor() {
if (isRecipientsEditorVisible()) {
return;
}
// Must grab the recipients before the view is made visible because getRecipients()
// returns empty recipients when the editor is visible.
ContactList recipients = getRecipients();
if (null == mRecipientsEditor) {/* add for HUAWEI bug by luning at 2011.12.27 */
ViewStub stub = (ViewStub) findViewById(R.id.recipients_editor_stub);
if (stub != null) {
mRecipientsEditor = (RecipientsEditor) stub.inflate();
} else {
LinearLayout parentLayout = (LinearLayout) findViewById(R.id.recipients_send);
if (parentLayout == null) {
Log.i(TAG,"LinearLayout parentLayout = (LinearLayout) findViewById(R.id.recipients_send); Finish");
finish();
}
stub = new ViewStub(this, R.layout.recipients_editor);
stub.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT,1.0f));
parentLayout.addView(stub, 0);
mRecipientsEditor = (RecipientsEditor) stub.inflate();
}
}
mRecipientsEditor.setAdapter(new RecipientsAdapter(this));
// for fix bug 14109 start.
//mRecipientsEditor.populate(recipients);
if ((DRAFTS.equals(boxType) || OUTBOX.equals(boxType) || SENT.equals(boxType))
&& (MessageBoxActivity.mBoxMsgRecipients != null)) {
mRecipientsEditor.populate(MessageBoxActivity.mBoxMsgRecipients);
} else {
mRecipientsEditor.populate(recipients);
}
// for fix bug 14109 end.
mRecipientsEditor.setOnCreateContextMenuListener(mRecipientsMenuCreateListener);
mRecipientsEditor.addTextChangedListener(mRecipientsWatcher);
mRecipientsEditor.setFilters(new InputFilter[] {
new InputFilter.LengthFilter(RECIPIENTS_MAX_LENGTH) });
mRecipientsEditor.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// After the user selects an item in the pop-up contacts list, move the
// focus to the text editor if there is only one recipient. This helps
// the common case of selecting one recipient and then typing a message,
// but avoids annoying a user who is trying to add five recipients and
// keeps having focus stolen away.
if (mRecipientsEditor.getRecipientCount() == 1 && mTextEditor != null) {
// if we're in extract mode then don't request focus
final InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputManager == null || (inputManager != null && !inputManager.isFullscreenMode())) {
mTextEditor.requestFocus();
}
}
}
});
mRecipientsEditor.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
RecipientsEditor editor = (RecipientsEditor) v;
ContactList contacts = editor.constructContactsFromInput();
updateTitle(contacts);
}
}
});
/* modify for HUAWEI bug by luning at 2011.12.27 begin */
mRecipientsEditor.setVisibility(View.VISIBLE);
if(null != mContactsSelectButton){
mContactsSelectButton.setVisibility(View.VISIBLE);
}
/* modify for HUAWEI bug by luning at 2011.12.27 end */
if (mTopPanel != null) {
mTopPanel.setVisibility(View.VISIBLE);
}
}
//==========================================================
// Activity methods
//==========================================================
public static boolean cancelFailedToDeliverNotification(Intent intent, Context context) {
if (MessagingNotification.isFailedToDeliver(intent)) {
// Cancel any failed message notifications
MessagingNotification.cancelNotification(context,
MessagingNotification.MESSAGE_FAILED_NOTIFICATION_ID);
return true;
}
return false;
}
public static boolean cancelFailedDownloadNotification(Intent intent, Context context) {
if (MessagingNotification.isFailedToDownload(intent)) {
// Cancel any failed download notifications
MessagingNotification.cancelNotification(context,
MessagingNotification.DOWNLOAD_FAILED_NOTIFICATION_ID);
return true;
}
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
System.gc();
super.onCreate(savedInstanceState);
//yeezone:jinwei add custom title
mContextView = (LinearLayout)((LayoutInflater)getSystemService(
Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.compose_message_activity, null);
if(FeatureSwitch.COMPOSE_MESSAGE_TIP_SUPPORT){
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
// setContentView(R.layout.compose_message_activity);
setContentView(mContextView);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.customize_title_compose_message);
}else{
// setContentView(R.layout.compose_message_activity);
setContentView(mContextView);
}
mSimChooserDialg=new SimChooserDialog(this);
mTelephonyManager = (TelephonyManager)getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
setProgressBarVisibility(false);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
// Initialize members for UI elements.
initResourceRefs();
mContentResolver = getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(mContentResolver);
initialize(savedInstanceState, 0);
if (TRACE) {
android.os.Debug.startMethodTracing("compose");
}
}
private void showSubjectEditor(boolean show) {
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("" + show);
}
if (mSubjectTextEditor == null) {
// Don't bother to initialize the subject editor if
// we're just going to hide it.
if (show == false) {
return;
}
mSubjectTextEditor = (EditText)findViewById(R.id.subject);
}
mSubjectTextEditor.setOnKeyListener(show ? mSubjectKeyListener : null);
synchronized(mSubjectTextEditor) {
if (show) {
mSubjectTextEditor.addTextChangedListener(mSubjectEditorWatcher);
} else {
mSubjectTextEditor.removeTextChangedListener(mSubjectEditorWatcher);
}
if(mWorkingMessage!=null && mWorkingMessage.hasSubject()){
mSubjectTextEditor.setText(mWorkingMessage.getSubject());
}else{
mSubjectTextEditor.setText("");
}
}
mSubjectTextEditor.setVisibility(show ? View.VISIBLE : View.GONE);
hideOrShowTopPanel();
}
private void hideOrShowTopPanel() {
boolean anySubViewsVisible = (isSubjectEditorVisible() || isRecipientsEditorVisible());
// === modify by luning at 11-09-02 begin ===
if(isRecipientsEditorVisible()){
mContactsSelectButton.setVisibility(View.VISIBLE);
}else{
mContactsSelectButton.setVisibility(View.GONE);
}
// === modify by luning at 11-09-02 end ===
if (SENT.equals(boxType) || OUTBOX.equals(boxType)) {
mTopPanel.setVisibility(View.GONE);
} else {
mTopPanel.setVisibility(anySubViewsVisible ? View.VISIBLE : View.GONE);
}
}
public void initialize(Bundle savedInstanceState, long originalThreadId) {
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if (bundle != null) {
boxmsgFlg = bundle.getString("boxmsgFlg");
boxmsgThreadId = bundle.getString("boxmsgThreadId");
boxmsgMsgId = bundle.getString("boxmsgMsgId");
boxType = bundle.getString("boxType");
} else {
boxmsgFlg = "false";
boxmsgThreadId = originalThreadId + "";
boxType = "";
}
// Create a new empty working message.
mWorkingMessage = WorkingMessage.createEmpty(this);
// Read parameters or previously saved state of this activity. This will load a new
// mConversation
initActivityState(savedInstanceState, intent, bundle);
if (LogTag.SEVERE_WARNING && originalThreadId != 0 &&
originalThreadId == mConversation.getThreadId()) {
LogTag.warnPossibleRecipientMismatch("ComposeMessageActivity.initialize: " +
" threadId didn't change from: " + originalThreadId, this);
}
log("savedInstanceState = " + savedInstanceState +
" intent = " + intent +
" mConversation = " + mConversation);
if (cancelFailedToDeliverNotification(getIntent(), this)) {
// Show a pop-up dialog to inform user the message was
// failed to deliver.
undeliveredMessageDialog(getMessageDate(null));
}
cancelFailedDownloadNotification(getIntent(), this);
// Set up the message history ListAdapter
initMessageList();
// Show the recipients editor if we don't have a valid thread. Hide it otherwise.
if (mConversation.getThreadId() <= 0) {
// Hide the recipients editor so the call to initRecipientsEditor won't get
// short-circuited.
hideRecipientEditor();
initRecipientsEditor();
// Bring up the softkeyboard so the user can immediately enter recipients. This
// call won't do anything on devices with a hard keyboard.
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
} else {
hideRecipientEditor();
}
// Load the draft for this thread, if we aren't already handling
// existing data, such as a shared picture or forwarded message.
boolean isForwardedMessage = false;
if (!handleSendIntent(intent)) {
isForwardedMessage = handleForwardedMessage();
if (!isForwardedMessage) {
loadDraft();
}
}
// Let the working message know what conversation it belongs to
mWorkingMessage.setConversation(mConversation);
updateSendButtonState();
drawTopPanel();
drawBottomPanel();
mAttachmentEditor.update(mWorkingMessage);
Configuration config = getResources().getConfiguration();
mIsKeyboardOpen = config.keyboardHidden == KEYBOARDHIDDEN_NO;
mIsLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE;
onKeyboardStateChanged(mIsKeyboardOpen);
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("update title, mConversation=" + mConversation.toString());
}
updateTitle(mConversation.getRecipients());
if (isForwardedMessage && isRecipientsEditorVisible()) {
// The user is forwarding the message to someone. Put the focus on the
// recipient editor rather than in the message editor.
mRecipientsEditor.requestFocus();
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Conversation conversation = null;
mSentMessage = false;
notificationFlg = true;
// If we have been passed a thread_id, use that to find our
// conversation.
// Note that originalThreadId might be zero but if this is a draft and we save the
// draft, ensureThreadId gets called async from WorkingMessage.asyncUpdateDraftSmsMessage
// the thread will get a threadId behind the UI thread's back.
//long originalThreadId = mConversation.getThreadId();
Bundle bundle = intent.getExtras();
if (bundle != null) {
boxmsgThreadId = bundle.getString("boxmsgThreadId");
}
long threadId = intent.getLongExtra("thread_id", 0);
Uri intentUri = intent.getData();
boolean sameThread = false;
if (threadId > 0 && !"true".equals(boxmsgFlg)) {
conversation = Conversation.get(this, threadId, false);
} else {
if (mConversation.getThreadId() == 0) {
// We've got a draft. See if the new intent's recipient is the same as
// the draft's recipient. First make sure the working recipients are synched
// to the conversation.
mWorkingMessage.syncWorkingRecipients();
sameThread = mConversation.sameRecipient(intentUri);
}
if (!sameThread) {
// Otherwise, try to get a conversation based on the
// data URI passed to our intent.
conversation = Conversation.get(this, intentUri, false);
}
}
if (LogTag.VERBOSE || DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("data=" + intentUri + ", thread_id extra is " + threadId +
", new conversation=" + conversation + ", mConversation=" + mConversation);
}
if (conversation != null) {
// Don't let any markAsRead DB updates occur before we've loaded the messages for
// the thread.
conversation.blockMarkAsRead(true);
// this is probably paranoia to compare both thread_ids and recipient lists,
// but we want to make double sure because this is a last minute fix for Froyo
// and the previous code checked thread ids only.
// (we cannot just compare thread ids because there is a case where mConversation
// has a stale/obsolete thread id (=1) that could collide against the new thread_id(=1),
// even though the recipient lists are different)
sameThread = (conversation.getThreadId() == mConversation.getThreadId() &&
conversation.equals(mConversation));
}
if (sameThread && (!"true".equals(boxmsgFlg))) {
log("same conversation");
} else {
if (LogTag.VERBOSE || DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("different conversation");
}
saveDraft(); // if we've got a draft, save it first
long originalThreadId = conversation.getThreadId();
if (mMsgListAdapter != null) {
mMsgListAdapter = null;
}
initialize(null, originalThreadId);
loadMessageContent();
}
}
@Override
protected void onRestart() {
super.onRestart();
if (mWorkingMessage.isDiscarded()) {
// If the message isn't worth saving, don't resurrect it. Doing so can lead to
// a situation where a new incoming message gets the old thread id of the discarded
// draft. This activity can end up displaying the recipients of the old message with
// the contents of the new message. Recognize that dangerous situation and bail out
// to the ConversationList where the user can enter this in a clean manner.
if (mWorkingMessage.isWorthSaving()) {
mWorkingMessage.unDiscard(); // it was discarded in onStop().
} else if (isRecipientsEditorVisible()) {
//for bug 17097 --start---
Log.i(TAG, "onRestart: don't goToConversationList");
//goToConversationList();
//for bug 17097 --end---
} else {
loadDraft();
mWorkingMessage.setConversation(mConversation);
mAttachmentEditor.update(mWorkingMessage);
}
}
}
@Override
protected void onStart() {
super.onStart();
mConversation.blockMarkAsRead(true);
initFocus();
// Register a BroadcastReceiver to listen on HTTP I/O process.
registerReceiver(mHttpProgressReceiver, mHttpProgressFilter);
loadMessageContent();
// Update the fasttrack info in case any of the recipients' contact info changed
// while we were paused. This can happen, for example, if a user changes or adds
// an avatar associated with a contact.
mWorkingMessage.syncWorkingRecipients();
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("update title, mConversation=" + mConversation.toString());
}
updateTitle(mConversation.getRecipients());
// Listen for broadcast intents that indicate the SMS is ready
IntentFilter filter = new IntentFilter();
if(MessageUtils.isMSMS){
filter.addAction(PhoneFactory.getAction(TelephonyIntents.ACTION_IS_SIM_SMS_READY, 0));
filter.addAction(PhoneFactory.getAction(TelephonyIntents.ACTION_IS_SIM_SMS_READY, 1));
}else{
filter.addAction(TelephonyIntents.ACTION_IS_SIM_SMS_READY);
}
filter.addAction("sendMmsReadReport");
registerReceiver(mReceiver, filter);
}
public void loadMessageContent() {
startMsgListQuery();
updateSendFailedNotification();
drawBottomPanel();
}
private void updateSendFailedNotification() {
final long threadId = mConversation.getThreadId();
if (threadId <= 0)
return;
// updateSendFailedNotificationForThread makes a database call, so do the work off
// of the ui thread.
new Thread(new Runnable() {
public void run() {
MessagingNotification.updateSendFailedNotificationForThread(
ComposeMessageActivity.this, threadId);
}
}, "updateSendFailedNotification").start();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("recipients", getRecipients().serialize());
mWorkingMessage.writeStateToBundle(outState);
if (mExitOnSent) {
outState.putBoolean("exit_on_sent", mExitOnSent);
}
}
@Override
protected void onResume() {
super.onResume();
// OLD: get notified of presence updates to update the titlebar.
// NEW: we are using ContactHeaderWidget which displays presence, but updating presence
// there is out of our control.
//Contact.startPresenceObserver();
addRecipientsListeners();
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("update title, mConversation=" + mConversation.toString());
}
// There seems to be a bug in the framework such that setting the title
// here gets overwritten to the original title. Do this delayed as a
// workaround.
mMessageListItemHandler.postDelayed(new Runnable() {
public void run() {
//ContactList recipients = isRecipientsEditorVisible() ?
//mRecipientsEditor.constructContactsFromInput() : getRecipients();
/*-------------------------by lai----------------------------*/
ContactList recipients;
if (isRecipientsEditorVisible()) {
recipients = mRecipientsEditor.constructContactsFromInput();
} else {
recipients = getRecipients();
String[] PhoneNums = recipients.getNumbers();
mPhoneNumForMms = PhoneNums[PhoneNums.length-1];
}
/*-------------------------by lai----------------------------*/
updateTitle(recipients);
}
}, 100);
//yeezone:jinwei
if(FeatureSwitch.PHONE_REJECT_AUTO_SENT_SUPPORT){
Bundle bundle = this.getIntent().getExtras();
if(bundle != null && bundle.getBoolean("auto_send"))
confirmSendMessageIfNeeded();
}
/*TDFAE00015859********************************/
Intent intent = getIntent();
int mAction = intent.getIntExtra("mAction",-1);
if(mAction == 0){
resolveContacts(intent);
}
/*TDFAE00015859******************************/
}
@Override
protected void onPause() {
super.onPause();
// OLD: stop getting notified of presence updates to update the titlebar.
// NEW: we are using ContactHeaderWidget which displays presence, but updating presence
// there is out of our control.
//Contact.stopPresenceObserver();
if (!is_vcard_adding) {
removeRecipientsListeners();
}
if (mAttachmentTypeSelectorAdapter != null) {
mAttachmentTypeSelectorAdapter.clear();
mAttachmentTypeSelectorAdapter = null;
}
if (mAttachmentDialogBuilder != null) {
mAttachmentDialogBuilder.setAdapter(null, null);
mAttachmentDialogBuilder = null;
}
if (mAttachmentDialog != null) {
mAttachmentDialog.cancel();
mAttachmentDialog = null;
}
}
@Override
protected void onStop() {
super.onStop();
if (!is_vcard_adding) {
InputMethodManager imm = ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE));
if (imm != null && ComposeMessageActivity.this.getCurrentFocus() != null) {
imm.hideSoftInputFromWindow(ComposeMessageActivity.this.getCurrentFocus()
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
if (mMsgListAdapter != null && mMsgListAdapter.getMessageItemCache() != null) {
mMsgListAdapter.getMessageItemCache().clear();
}
if (mMsgListAdapter != null && mMsgListAdapter.getAddressToMessageListItems() != null) {
mMsgListAdapter.getAddressToMessageListItems().clear();
}
// Allow any blocked calls to update the thread's read status.
mConversation.blockMarkAsRead(false);
if (mMsgListAdapter != null) {
mMsgListAdapter.changeCursor(null);
}
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("save draft");
}
if (mRecipientsEditor != null && isRecipientsEditorVisible()
&& !mRecipientsEditor.hasValidRecipient(mWorkingMessage.requiresMms())) {
return;
}
saveDraft();
// Cleanup the BroadcastReceiver.
unregisterReceiver(mHttpProgressReceiver);
}
}
/* fixed CR<NEWMS119944 NEWMS119757 NEWMS119755 NEWMS120030 NEWMS119256> by lino release memory */
private void destroy(){
HashMap<String, HashSet<MessageListItem>> addToMessLI = mMsgListAdapter.getAddressToMessageListItems();
Iterator<String> it = addToMessLI.keySet().iterator();
HashSet<MessageListItem> hashSetMLI = null;
MessageListItem mlt = null;
MessageItem mi = null;
BitmapDrawable bd = null;
ImageModel imageModel = null;
while(it.hasNext()){
hashSetMLI = addToMessLI.get(it.next());
Iterator<MessageListItem> i = hashSetMLI.iterator();
while(i.hasNext()){
mlt = i.next();
mlt.destroy();
mlt.removeAllViewsInLayout();
mlt = null;
}
hashSetMLI.clear();
hashSetMLI = null;
}
addToMessLI.clear();
addToMessLI = null;
if (mMsgListAdapter != null && mMsgListAdapter.getMessageItemCache() != null) {
mMsgListAdapter.getMessageItemCache().clear();
}
if (mAttachmentDialogBuilder != null) {
mAttachmentDialogBuilder.setAdapter(null, null);
mAttachmentDialogBuilder = null;
}
if (mAttachmentDialog != null) {
mAttachmentDialog.cancel();
mAttachmentDialog = null;
}
// if (mMsgListAdapter != null) {
// LinkedHashMap<Long, MessageItem> msgItemCatch = mMsgListAdapter.getMessageItemCache();
// if (null != msgItemCatch) {
// MessageItem msgItem = null;
// Model model = null;
// SlideModel slide = null;
//
// Iterator iterator = msgItemCatch.entrySet().iterator();
// while (iterator.hasNext()) {
// Map.Entry entry = (Map.Entry) iterator.next();
// msgItem = (MessageItem) entry.getValue();
// if (msgItem != null) {
// model = (SlideshowModel) msgItem.mSlideshow;
// if (model != null) {
// slide = ((SlideshowModel) model).get(0);
// if (null != slide) {
// if (slide.hasImage()) {
// imageModel = slide.getImage();
//
// Bitmap bitMap = imageModel.getBitmapCache();/* fixed CR<NEWMS00138991> by luning at 2011.11.10*/
//// Bitmap bitMap = imageModel.getBitmap();
//
// if (bitMap != null && !bitMap.isRecycled()) {
// Log.v("lino", "mMessageItemCatch---!bitMap.isRecycled()");
// bitMap.recycle();
// bitMap = null;
// }
// }
// }
// slide = null;
// }
// }
// imageModel = null;
// }
//
// msgItemCatch.clear();
// msgItemCatch = null;
// }
// }
//===== fixed CR<NEWMS00127096,NEWMS00127018,NEWMS00126971,NEWMS00127071> by luning at 11-09-29 begin=====
if(mCursor != null){
mCursor.close();
// mCursor = null;
}
mMsgListView.removeAllViewsInLayout();
mMsgListView.setAdapter(null);
// mMsgListAdapter = null;
if(mTopPanel != null){
((LinearLayout)mTopPanel).removeAllViewsInLayout();
// mTopPanel = null;
}
if(mBottomPanel != null){
((LinearLayout)mBottomPanel).removeAllViewsInLayout();
// mBottomPanel = null;
}
if(mTextEditor != null){
mTextEditor.setOnEditorActionListener(null);
//for bugzilla 13981
//mTextEditor.addTextChangedListener(null);
// mTextEditor = null;
}
// if(mTextCounter != null){
// mTextCounter = null;
// }
if(mSendButton != null){
mSendButton.setOnClickListener(null);
// mSendButton = null;
}
if(mContactsSelectButton != null){
mContactsSelectButton.setOnClickListener(null);
// mContactsSelectButton = null;
}
if(mSubjectTextEditor != null){
mSubjectTextEditor.setOnEditorActionListener(null);
//for bugzilla 13981
//mSubjectTextEditor.addTextChangedListener(null);
// mSubjectTextEditor = null;
}
if(mRecipientsEditor != null){
//for bugzilla 13981
//mRecipientsEditor.addTextChangedListener(null);
// mRecipientsEditor = null;
}
mAttachmentEditor.destroy();
mAttachmentEditor.removeAllViewsInLayout();
// mAttachmentEditor = null;
mContextView.removeAllViewsInLayout();
notificationFlg = false;
// mContextView = null;
// mWorkingMessage = null;
// list = null;
// mAttachmentEditorHandler = null;
// mBackgroundQueryHandler = null;
// mConversation = null;
// mContentResolver = null;
// mDataSetChangedListener = null;
// mHttpProgressFilter = null;
// mHttpProgressReceiver = null;
// mTitleLeft = null;
// mTitleRight = null;
// mTextEditorWatcher = null;
// mMessageListItemHandler = null;
// mMsgListMenuCreateListener = null;
// mMsgListView = null;
//===== fixed CR<NEWMS00127096,NEWMS00127018,NEWMS00126971,NEWMS00127071> by luning at 11-09-29 end=====
// if(!mCreate){
// ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
// am.killBackgroundProcesses(getPackageName());
// }
}
@Override
protected void onDestroy() {
if (TRACE) {
android.os.Debug.stopMethodTracing();
}
// list.clear();/*delete for CR<NEWMS00135995> by luning at 11-11-04 */
destroy();
super.onDestroy();
System.gc();
unregisterReceiver(mReceiver);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (LOCAL_LOGV) {
Log.v(TAG, "onConfigurationChanged: " + newConfig);
}
mIsKeyboardOpen = newConfig.keyboardHidden == KEYBOARDHIDDEN_NO;
boolean isLandscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
if (mIsLandscape != isLandscape) {
mIsLandscape = isLandscape;
// Have to re-layout the attachment editor because we have different layouts
// depending on whether we're portrait or landscape.
mAttachmentEditor.update(mWorkingMessage);
}
onKeyboardStateChanged(mIsKeyboardOpen);
}
private void onKeyboardStateChanged(boolean isKeyboardOpen) {
// If the keyboard is hidden, don't show focus highlights for
// things that cannot receive input.
if (isKeyboardOpen) {
if (mRecipientsEditor != null) {
mRecipientsEditor.setFocusableInTouchMode(true);
}
if (mSubjectTextEditor != null) {
mSubjectTextEditor.setFocusableInTouchMode(true);
}
mTextEditor.setFocusableInTouchMode(true);
mTextEditor.setHint(R.string.type_to_compose_text_enter_to_send);
} else {
if (mRecipientsEditor != null) {
mRecipientsEditor.setFocusable(false);
}
if (mSubjectTextEditor != null) {
mSubjectTextEditor.setFocusable(false);
}
mTextEditor.setFocusable(false);
mTextEditor.setHint(R.string.open_keyboard_to_compose_message);
}
}
@Override
public void onUserInteraction() {
checkPendingNotification();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
checkPendingNotification();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DEL:
if ((mMsgListAdapter != null) && mMsgListView.isFocused()) {
Cursor cursor;
try {
cursor = (Cursor) mMsgListView.getSelectedItem();
} catch (ClassCastException e) {
Log.e(TAG, "Unexpected ClassCastException.", e);
return super.onKeyDown(keyCode, event);
}
if (cursor != null) {
boolean locked = cursor.getInt(COLUMN_MMS_LOCKED) != 0;
DeleteMessageListener l = new DeleteMessageListener(
cursor.getLong(COLUMN_ID),
cursor.getString(COLUMN_MSG_TYPE),
locked);
confirmDeleteDialog(l, locked);
return true;
}
}
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if (isPreparedForSending()) {
confirmSendMessageIfNeeded();
return true;
}
break;
case KeyEvent.KEYCODE_BACK:
exitComposeMessageActivity(new Runnable() {
public void run() {
finish();
}
});
return true;
}
return super.onKeyDown(keyCode, event);
}
private void exitComposeMessageActivity(final Runnable exit) {
// If the message is empty, just quit -- finishing the
// activity will cause an empty draft to be deleted.
if (!mWorkingMessage.isWorthSaving()) {
exit.run();
return;
}
// fix bug 10287&10572
if (isRecipientsEditorVisible() &&
!mRecipientsEditor.hasValidRecipient(mWorkingMessage.requiresMms())) {
MessageUtils.showDiscardDraftConfirmDialog(this, new DiscardDraftListener());
return;
}
//saveDraft();
// fix bug 21561
if (mWorkingMessage.getWorkingRecipients() == null && mRecipientsEditor != null) {
mWorkingMessage.setWorkingRecipients(mRecipientsEditor.getNumbers());
}
mToastForDraftSave = true;
exit.run();
}
private void goToConversationList() {
finish();
startActivity(new Intent(this, ConversationList.class));
}
private void hideRecipientEditor() {
if (mRecipientsEditor != null) {
mRecipientsEditor.removeTextChangedListener(mRecipientsWatcher);
mRecipientsEditor.setVisibility(View.GONE);
hideOrShowTopPanel();
}
}
private boolean isRecipientsEditorVisible() {
return (null != mRecipientsEditor)
&& (View.VISIBLE == mRecipientsEditor.getVisibility());
}
private boolean isSubjectEditorVisible() {
return (null != mSubjectTextEditor)
&& (View.VISIBLE == mSubjectTextEditor.getVisibility());
}
private boolean composeIsWapush() {
Cursor cursor = mMsgListAdapter.getCursor();
boolean isWapPush = false;
if (cursor == null || cursor.getCount() == 0) {
return false;
}
if (cursor != null) {
if (cursor.moveToFirst()) {
int threadId = cursor.getInt(MessageListAdapter.COLUMN_THREAD_ID);
Cursor cursorWap = getContentResolver().query(
Sms.Inbox.CONTENT_URI, new String[] { "_id" },
"wap_push=1 and thread_id = " + threadId, null, null);
if (cursorWap != null && cursorWap.getCount() > 0) {
isWapPush = true;
}
if (cursorWap != null) {
cursorWap.close();
}
}
}
return isWapPush;
}
public void onAttachmentChanged() {
// Have to make sure we're on the UI thread. This function can be called off of the UI
// thread when we're adding multi-attachments
runOnUiThread(new Runnable() {
public void run() {
drawBottomPanel();
updateSendButtonState();
mAttachmentEditor.update(mWorkingMessage);
}
});
}
public void onProtocolChanged(final boolean mms) {
// Have to make sure we're on the UI thread. This function can be called off of the UI
// thread when we're adding multi-attachments
runOnUiThread(new Runnable() {
public void run() {
toastConvertInfo(mms);
setSendButtonText(mms);
}
});
}
private void setSendButtonText(boolean isMms) {
Button sendButton = mSendButton;
sendButton.setText(R.string.send);
if (isMms) {
// Create and append the "MMS" text in a smaller font than the "Send" text.
sendButton.append("\n");
SpannableString spannable = new SpannableString(getString(R.string.mms));
int mmsTextSize = (int) (sendButton.getTextSize() * 0.75f);
spannable.setSpan(new AbsoluteSizeSpan(mmsTextSize), 0, spannable.length(), 0);
sendButton.append(spannable);
//===== fixed CR<NEWMS00134916> by luning at 11-10-28 begin =====
// mTextCounter.setText("");
resetCounter();
//===== fixed CR<NEWMS00134916> by luning at 11-10-28 end =====
}
else{
reCalcSmsCounter(mTextEditor.getText());
}
}
Runnable mResetMessageRunnable = new Runnable() {
public void run() {
resetMessage();
}
};
public void onPreMessageSent() {
//resetMessage();
runOnUiThread(mResetMessageRunnable);
}
public void onMessageSent() {
// If we already have messages in the list adapter, it
// will be auto-requerying; don't thrash another query in.
if (mMsgListAdapter.getCount() == 0) {
startMsgListQuery();
long threadid = mConversation.getThreadId();
mConversation.loadFromThreadId(threadid, false);
}
}
public void onMaxPendingMessagesReached() {
saveDraft();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(ComposeMessageActivity.this, R.string.too_many_unsent_mms,
Toast.LENGTH_LONG).show();
}
});
}
public void onAttachmentError(final int error) {
runOnUiThread(new Runnable() {
public void run() {
handleAddAttachmentError(error, R.string.type_picture);
onMessageSent(); // now requery the list of messages
}
});
}
// We don't want to show the "call" option unless there is only one
// recipient and it's a phone number.
private boolean isRecipientCallable() {
ContactList recipients = getRecipients();
return (recipients.size() == 1 && !recipients.containsEmail());
}
public static Intent getVPIntent(Intent intent){
return intent.putExtra(EXTRA_IS_VIDEOCALL, true);
}
private void dialRecipient() {
String number = getRecipients().get(0).getNumber();
Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number));
startActivity(dialIntent);
}
private void videodialRecipient() {
String number = getRecipients().get(0).getNumber();
Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number));
startActivity(getVPIntent(dialIntent));
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (isRecipientCallable() && !composeIsWapush()) {
menu.add(0, MENU_CALL_RECIPIENT, 0, R.string.menu_call).setIcon(
R.drawable.ic_menu_call);
if (TelephonyManager.MODEM_TYPE_TDSCDMA == TelephonyManager
.getDefault().getModemType()
&& SystemProperties
.getBoolean("ro.device.support.vt", true)) {
menu.add(0, MENU_VIDEOCALL_RECIPIENT, 0, R.string.menu_videocall).setIcon(
R.drawable.ic_menu_call);
}
}
// Only add the "View contact" menu item when there's a single recipient and that
// recipient is someone in contacts.
ContactList recipients = getRecipients();
if (recipients.size() == 1 && recipients.get(0).existsInDatabase()) {
menu.add(0, MENU_VIEW_CONTACT, 0, R.string.menu_view_contact).setIcon(
R.drawable.ic_menu_contact);
}
if (MmsConfig.getMmsEnabled()) {
if (!isSubjectEditorVisible() && !SENT.equals(boxType) && (!OUTBOX.equals(boxType) || outboxEditMsgFlg)) {
menu.add(0, MENU_ADD_SUBJECT, 0, R.string.add_subject).setIcon(
R.drawable.ic_menu_edit);
}
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 begin======
// if (!mWorkingMessage.hasAttachment()) {
if(!SENT.equals(boxType) && (!OUTBOX.equals(boxType) || outboxEditMsgFlg))/*add by luning :only send vcardPart when pduBody have it for the moment*/
menu.add(0, MENU_ADD_ATTACHMENT, 0, R.string.add_attachment).setIcon(
R.drawable.ic_menu_attachment);
// }
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 end======
}
if (isPreparedForSending() && !SENT.equals(boxType) && (!OUTBOX.equals(boxType) || outboxEditMsgFlg)) {
menu.add(0, MENU_SEND, 0, R.string.send).setIcon(android.R.drawable.ic_menu_send);
}
/*======fixed CR<NEWMS00153060> by luning at 11-12-26 begin======*/
if ((!mWorkingMessage.requiresMms() || !mWorkingMessage.hasSlideshow()
|| mWorkingMessage.getSlideshow().isSimpleSlide()) && !SENT.equals(boxType) && (!OUTBOX.equals(boxType) || outboxEditMsgFlg)
&&mTextEditor.hasFocus()
)
/*======fixed CR<NEWMS00153060> by luning at 11-12-26 end======*/
{
menu.add(0, MENU_INSERT_SMILEY, 0, R.string.menu_insert_smiley).setIcon(
R.drawable.ic_menu_emoticons);
}
if (mMsgListAdapter.getCount() > 0 && !"true".equals(boxmsgFlg)) {
// Removed search as part of b/1205708
//menu.add(0, MENU_SEARCH, 0, R.string.menu_search).setIcon(
// R.drawable.ic_menu_search);
Cursor cursor = mMsgListAdapter.getCursor();
if ((null != cursor) && (cursor.getCount() > 0)) {
menu.add(0, MENU_DELETE_THREAD, 0, R.string.delete_thread).setIcon(
android.R.drawable.ic_menu_delete);
}
} else {
if (!SENT.equals(boxType) && (!OUTBOX.equals(boxType) || outboxEditMsgFlg)) {
menu.add(0, MENU_DISCARD, 0, R.string.discard).setIcon(android.R.drawable.ic_menu_delete);
}
}
if (!"true".equals(boxmsgFlg)) {
menu.add(0, MENU_CONVERSATION_LIST, 0, R.string.all_threads).setIcon(
R.drawable.ic_menu_friendslist);
}
buildAddAddressToContactMenuItem(menu);
return true;
}
private void buildAddAddressToContactMenuItem(Menu menu) {
// Look for the first recipient we don't have a contact for and create a menu item to
// add the number to contacts.
for (Contact c : getRecipients()) {
if (!c.existsInDatabase() && canAddToContacts(c) && !composeIsWapush()) {
Intent intent = ConversationList.createAddContactIntent(c.getNumber());
menu.add(0, MENU_ADD_ADDRESS_TO_CONTACTS, 0, R.string.menu_add_to_contacts)
.setIcon(android.R.drawable.ic_menu_add)
.setIntent(intent);
break;
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ADD_SUBJECT:
showSubjectEditor(true);
mWorkingMessage.setSubject("", true);
mSubjectTextEditor.requestFocus();
break;
case MENU_ADD_ATTACHMENT:
// Launch the add-attachment list dialog
IS_APPEND_MEDIA = true;
showAddAttachmentDialog(false);
break;
case MENU_DISCARD:
mWorkingMessage.discard();
finish();
break;
case MENU_SEND:
if (isPreparedForSending()) {
confirmSendMessageIfNeeded();
}
break;
case MENU_SEARCH:
onSearchRequested();
break;
case MENU_DELETE_THREAD:
confirmDeleteThread(mConversation.getThreadId());
break;
case MENU_CONVERSATION_LIST:
exitComposeMessageActivity(new Runnable() {
public void run() {
goToConversationList();
}
});
break;
case MENU_CALL_RECIPIENT:
dialRecipient();
break;
case MENU_VIDEOCALL_RECIPIENT:
videodialRecipient();
break;
case MENU_INSERT_SMILEY:
showSmileyDialog();
break;
case MENU_VIEW_CONTACT: {
// View the contact for the first (and only) recipient.
ContactList list = getRecipients();
if (list.size() == 1 && list.get(0).existsInDatabase()) {
Uri contactUri = list.get(0).getUri();
Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(intent);
}
break;
}
case MENU_ADD_ADDRESS_TO_CONTACTS:
mAddContactIntent = item.getIntent();
startActivityForResult(mAddContactIntent, REQUEST_CODE_ADD_CONTACT);
break;
}
return true;
}
private void confirmDeleteThread(long threadId) {
Conversation.startQueryHaveLockedMessages(mBackgroundQueryHandler,
threadId, ConversationList.HAVE_LOCKED_MESSAGES_TOKEN);
}
// static class SystemProperties { // TODO, temp class to get unbundling working
// static int getInt(String s, int value) {
// return value; // just return the default value or now
// }
// }
private int getVideoCaptureDurationLimit() {
return CamcorderProfile.get(CamcorderProfile.QUALITY_LOW).duration;
}
private void addAttachment(int type, boolean replace) {
// Calculate the size of the current slide if we're doing a replace so the
// slide size can optionally be used in computing how much room is left for an attachment.
//Lino modify for NEWMS00136133 begin 2011-11-03
((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
//Lino modify for NEWMS00136133 end 2011-11-03
int currentSlideSize = 0;
SlideshowModel slideShow = mWorkingMessage.getSlideshow();
if (replace && slideShow != null) {
SlideModel slide = slideShow.get(0);
currentSlideSize = slide.getSlideSize();
}
switch (type) {
case AttachmentTypeSelectorAdapter.ADD_IMAGE:
MessageUtils.selectImage(this, REQUEST_CODE_ATTACH_IMAGE);
break;
case AttachmentTypeSelectorAdapter.TAKE_PICTURE: {
Log.d(TAG, "position take picture ");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//intent.putExtra(MediaStore.EXTRA_OUTPUT, Mms.ScrapSpace.CONTENT_URI);
intent.putExtra(MediaStore.EXTRA_OUTPUT, TempFileProvider.SCRAP_CONTENT_URI);
startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);
break;
}
case AttachmentTypeSelectorAdapter.ADD_VIDEO:
MessageUtils.selectVideo(this, REQUEST_CODE_ATTACH_VIDEO);
break;
case AttachmentTypeSelectorAdapter.RECORD_VIDEO:
long sizeLimit = computeAttachmentSizeLimit(slideShow, currentSlideSize);
if (sizeLimit > 0) {
int durationLimit = getVideoCaptureDurationLimit();
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
intent.putExtra("android.intent.extra.sizeLimit", sizeLimit);
intent.putExtra("android.intent.extra.durationLimit", durationLimit);
startActivityForResult(intent, REQUEST_CODE_TAKE_VIDEO);
} else {
Toast.makeText(this,
getString(R.string.message_too_big_for_video),
Toast.LENGTH_SHORT).show();
}
break;
case AttachmentTypeSelectorAdapter.ADD_SOUND:
MessageUtils.selectAudio(this, REQUEST_CODE_ATTACH_SOUND);
break;
case AttachmentTypeSelectorAdapter.RECORD_SOUND:
MessageUtils.recordSound(this, REQUEST_CODE_RECORD_SOUND);
break;
case AttachmentTypeSelectorAdapter.ADD_VCARD:
Intent mintent = new Intent("com.android.contacts.MULTIOPERATELIST");
mintent.putExtra("mode", MODE_MMS_VCARD_CONTACTS);
mintent.putExtra("group", GROUP_ALL);
startActivityForResult(mintent, REQUEST_CODE_ADD_ATTACHMENT);
break;
case AttachmentTypeSelectorAdapter.ADD_SLIDESHOW:
editSlideshow();
break;
default:
break;
}
}
public static long computeAttachmentSizeLimit(SlideshowModel slideShow,
int currentSlideSize) {
// Set video size limit. Subtract 1K for some text.
long sizeLimit = MmsConfig.getMaxMessageSize() - SlideshowModel.SLIDESHOW_SLOP;
if (slideShow != null) {
sizeLimit -= slideShow.getTotalMsgSizeWithSlideHead();
// We're about to ask the camera to capture some video which will
// eventually replace the content on the current slide. Since the current
// slide already has some content (which was subtracted out just above)
// and that content is going to get replaced, we can add the size of the
// current slide into the available space used to capture a video.
sizeLimit += currentSlideSize;
}
return sizeLimit;
}
private void showAddAttachmentDialog(final boolean replace) {
if (mAttachmentTypeSelectorAdapter == null) {
mAttachmentTypeSelectorAdapter = new AttachmentTypeSelectorAdapter(
this, AttachmentTypeSelectorAdapter.MODE_WITH_SLIDESHOW);
}
if (mAttachmentDialogBuilder == null || replace) {
mAttachmentDialogBuilder = new AlertDialog.Builder(this);
mAttachmentDialogBuilder.setIcon(R.drawable.ic_dialog_attach);
mAttachmentDialogBuilder.setTitle(R.string.add_attachment);
mAttachmentDialogBuilder.setAdapter(mAttachmentTypeSelectorAdapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
addAttachment(mAttachmentTypeSelectorAdapter.buttonToCommand(which), replace);
dialog.dismiss();
}
});
}
if (mAttachmentDialog == null || replace) {
mAttachmentDialog = mAttachmentDialogBuilder.create();
}
mAttachmentDialog.show();
}
private void resolveContacts(Intent intent) {
// ArrayList<ContentValues> contacts =
// intent.getParcelableArrayListExtra("ContactsForMms");
// ===== fixed CR<NEWMS00135995> by luning at 11-11-04 begin =====
// String text = mRecipientsEditor.getText().toString().trim();
// int length = text.length();
// if(length != 0 && text.charAt(length - 1) != ','){
// mRecipientsEditor.append(", ");
// }
int contactSize = intent.getIntExtra("count", 0);
String contactStr = intent.getStringExtra("ContactsForMms");
// ===== fixed CR<NEWMS00135995> by luning at 11-11-04 end =====
if (contactSize > RECIPIENTS_MAX_MUBER && contactStr != null) {
final AlertDialog.Builder builder = new AlertDialog.Builder(ComposeMessageActivity.this);
builder.setTitle(R.string.to_many_contacts);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(R.string.to_many_contacts_body);
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
} else if (contactStr != null) {
//int temp=0;
StringBuffer allStr = new StringBuffer();
String[] singleStr = contactStr.split("\r\n");
String text=null;
for (int i = 0; i < contactSize; i++) {
text = mRecipientsEditor.getText().toString().trim();
int length = text.length();
if (length != 0 && text.charAt(length - 1) != ',') {
mRecipientsEditor.append(", ");
}
// ===== fixed CR<NEWMS00135995> by luning at 11-11-04 end =====
/*
* ContentValues map = contacts.get(i); String name =
* map.getAsString(Contacts.DISPLAY_NAME); String number =
* map.getAsString("number");
*/
String map = singleStr[i];
final String CR = "\r";
final String CRLF = "\r\n";
String[] sp = map.split(CR);
String name = sp[0];
String number = sp[1];
String nameAndnumber = "";
if (name.equals(number)) {
nameAndnumber = " <" + number + ">, ";
} else {
nameAndnumber = name + " <" + number + ">, ";
}
if (text.contains(nameAndnumber.trim())) {
continue;
}
// ===== fixed CR<NEWMS00135995> by luning at 11-11-04 end =====
SpannableString s = new SpannableString(nameAndnumber);
s.setSpan(new Annotation("name", name), 0, name.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new Annotation("number", number), 0, number.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
if ((mRecipientsEditor.length() + s.length()) >= RECIPIENTS_MAX_LENGTH ) {
//temp ++;
continue;
}
mRecipientsEditor.append(s);
// ===== fixed CR<NEWMS00135995> by luning at 11-11-04 end =====
}
}
mRecipientsEditor.requestFocus();
}
// modify by dory.zheng for NEWMS00137013 begin
// if(temp > 0){
// Toast.makeText(ComposeMessageActivity.this,
// R.string.contacts_max_exceed, Toast.LENGTH_SHORT)
// .show();
// }
// modify by dory.zheng for NEWMS00137013 end
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (DEBUG) {
log("requestCode=" + requestCode + ", resultCode=" + resultCode + ", data=" + data);
}
mWaitingForSubActivity = false; // We're back!
if (mWorkingMessage.isFakeMmsForDraft()) {
// We no longer have to fake the fact we're an Mms. At this point we are or we aren't,
// based on attachments and other Mms attrs.
mWorkingMessage.removeFakeMmsForDraft();
}
// If there's no data (because the user didn't select a picture and
// just hit BACK, for example), there's nothing to do.
//if (requestCode != REQUEST_CODE_TAKE_PICTURE) {
//if (data == null) {
// return;
//}
//} else if (resultCode != RESULT_OK){
if (resultCode != RESULT_OK){
if (DEBUG) log("bail due to resultCode=" + resultCode);
return;
}
switch(requestCode) {
case REQUEST_CODE_CREATE_SLIDESHOW:
if (data != null) {
CharSequence subject = mWorkingMessage.getSubject();
boolean notify = !mWorkingMessage.hasAttachment();
WorkingMessage newMessage = WorkingMessage.load(this, data.getData() ,notify);
if (newMessage != null) {
mWorkingMessage = newMessage;
mWorkingMessage.setConversation(mConversation);
mAttachmentEditor.update(mWorkingMessage);
mWorkingMessage.setSubject(subject, false);
drawTopPanel();
updateSendButtonState();
//if (mWorkingMessage.hasSlideshow()) {
// this.toastConvertInfo(true);
//} else {
// this.toastConvertInfo(false);
//}
}
}
break;
case REQUEST_CODE_TAKE_PICTURE: {
// create a file based uri and pass to addImage(). We want to read the JPEG
// data directly from file (using UriImage) instead of decoding it into a Bitmap,
// which takes up too much memory and could easily lead to OOM.
Log.d(TAG, "REQUEST_CODE_TAKE_PICTURE result");
Log.d(TAG, "new RotatePictureTask().execute((Void)null); Enter");
new RotatePictureTask().execute((Void)null);
Log.d(TAG, "new RotatePictureTask().execute((Void)null); Leave");
break;
}
case REQUEST_CODE_ATTACH_IMAGE: {
addImage(data.getData(), false);
break;
}
case REQUEST_CODE_TAKE_VIDEO:
case REQUEST_CODE_ATTACH_VIDEO:
addVideo(data.getData(), false);
break;
case REQUEST_CODE_ATTACH_SOUND: {
Uri uri = (Uri) data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
//----maybe the uri not sound,then the uri will be null.-start----
if (uri == null) {
Toast.makeText(ComposeMessageActivity.this, R.string.re_select_media,
Toast.LENGTH_SHORT).show();
break;
}
//----end.---------------------------------------------------------
if (Settings.System.DEFAULT_RINGTONE_URI.equals(uri)) {
break;
}
addAudio(uri, false);
break;
}
case REQUEST_CODE_RECORD_SOUND:
addAudio(data.getData(), false);
break;
case REQUEST_CODE_ECM_EXIT_DIALOG:
boolean outOfEmergencyMode = data.getBooleanExtra(EXIT_ECM_RESULT, false);
if (outOfEmergencyMode) {
sendMessage(false);
}
break;
case REQUEST_CODE_ADD_CONTACT:
// The user just added a new contact. We saved the contact info in
// mAddContactIntent. Get the contact and force our cached contact to
// get reloaded with the new info (such as contact name). After the
// contact is reloaded, the function onUpdate() in this file will get called
// and it will update the title bar, etc.
Log.i(TAG,"Add Contacts");
if (mAddContactIntent != null) {
String address =
mAddContactIntent.getStringExtra(ContactsContract.Intents.Insert.EMAIL);
if (address == null) {
address =
mAddContactIntent.getStringExtra(ContactsContract.Intents.Insert.PHONE);
}
if (address != null) {
Contact contact = Contact.get(address, false);
if (contact != null) {
contact.reload();
}
}
}
break;
//yeezone:jinwei add selected contacts
case REQUESET_CODE_SELECT_CONTACTS:
resolveContacts(data);
break;
case REQUEST_CODE_ADD_ATTACHMENT:
String type = data.getType();
Uri stream = (Uri)data.getParcelableExtra(Intent.EXTRA_STREAM);
addAttachment(type, stream, false);
default:
// TODO
break;
}
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 begin =====
//default is append media
//IS_APPEND_MEDIA = true;
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 end =====
}
private int getPositionOfadd() {
if (mWorkingMessage.getSlideshow() == null) {
Log.d(TAG, "mWorkingMessage.getSlideshow() == null");
return 0;
}
Log.d(TAG, "IS_APPEND_MEDIA == "+IS_APPEND_MEDIA);
if (!IS_APPEND_MEDIA) {
return 0;
}
SlideshowModel slides = mWorkingMessage.getSlideshow();
for (int i = 0; i < slides.size(); i++) {
if (!slides.get(i).hasImage() && !slides.get(i).hasVideo()) {
return i;
}
}
return slides.size();
}
private ResizeImageResultCallback mResizeImageCallback = new ResizeImageResultCallback() {
// TODO: make this produce a Uri, that's what we want anyway
public void onResizeResult(PduPart part, boolean append) {
if (part == null) {
handleAddAttachmentError(WorkingMessage.UNKNOWN_ERROR, R.string.type_picture);
return;
}
Context context = ComposeMessageActivity.this;
PduPersister persister = PduPersister.getPduPersister(context);
int result;
if(!mWorkingMessage.isDiscarded()) {
Uri messageUri = mWorkingMessage.saveAsMms(true);
try {
Uri dataUri = persister.persistPart(part, ContentUris.parseId(messageUri));
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 begin =====
// result = mWorkingMessage.setAttachment(WorkingMessage.IMAGE, dataUri, append);
result = mWorkingMessage.addAttachment(WorkingMessage.IMAGE, dataUri);
//===== fixed CR<NEWSM00125959> by luning at 11-09-26 end =====
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("ResizeImageResultCallback: dataUri=" + dataUri);
}
} catch (MmsException e) {
result = WorkingMessage.UNKNOWN_ERROR;
}
handleAddAttachmentError(result, R.string.type_picture);
}
}
};
private void handleAddAttachmentError(final int error, final int mediaTypeStringId) {
if (error == WorkingMessage.OK) {
return;
}
runOnUiThread(new Runnable() {
public void run() {
Resources res = getResources();
String mediaType = res.getString(mediaTypeStringId);
String title, message;
switch(error) {
case WorkingMessage.UNSUPPORTED_TYPE:
title = res.getString(R.string.unsupported_media_format, mediaType);
message = res.getString(R.string.select_different_media, mediaType);
break;
case WorkingMessage.MESSAGE_SIZE_EXCEEDED:
title = res.getString(R.string.exceed_message_size_limitation, mediaType);
message = res.getString(R.string.failed_to_add_media, mediaType);
break;
case WorkingMessage.IMAGE_TOO_LARGE:
title = res.getString(R.string.failed_to_resize_image);
message = res.getString(R.string.resize_image_error_information);
break;
case WorkingMessage.SLIDE_MAX:
message = res.getString(R.string.cannot_add_slide_anymore, mediaType);
Toast.makeText(ComposeMessageActivity.this, message, Toast.LENGTH_SHORT)
.show();
return;
case WorkingMessage.UNKNOWN_ERROR:
default:
message = res.getString(R.string.failed_to_add_media, mediaType);
Toast.makeText(ComposeMessageActivity.this, message, Toast.LENGTH_SHORT).show();
return;
// throw new IllegalArgumentException("unknown error " + error);
}
MessageUtils.showErrorDialog(ComposeMessageActivity.this, title, message);
}
});
}
private void addImage(Uri uri, boolean append) {
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("append=" + append + ", uri=" + uri + ", IS_APPEND_MEDIA= " + IS_APPEND_MEDIA
+ ", hasAttachment= " + mWorkingMessage.hasAttachment());
}
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 begin======
int result = 0;
if(IS_APPEND_MEDIA && mWorkingMessage.hasAttachment()){
result = mWorkingMessage.addAttachment(WorkingMessage.IMAGE, uri);
}else{
result = mWorkingMessage.setAttachment(WorkingMessage.IMAGE, uri, false);
}
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 end======
if (result == WorkingMessage.IMAGE_TOO_LARGE ||
result == WorkingMessage.MESSAGE_SIZE_EXCEEDED) {
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("resize image " + uri);
}
MessageUtils.resizeImageAsync(this,
uri, mAttachmentEditorHandler, mResizeImageCallback, append);
return;
}
handleAddAttachmentError(result, R.string.type_picture);
}
private void addVideo(Uri uri, boolean append) {
if (uri != null) {
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 begin======
int result = 0;
if (IS_APPEND_MEDIA && mWorkingMessage.hasAttachment()) {
result = mWorkingMessage.addAttachment(WorkingMessage.VIDEO, uri);
} else {
result = mWorkingMessage.setAttachment(WorkingMessage.VIDEO, uri, false);
}
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 end======
handleAddAttachmentError(result, R.string.type_video);
}
}
private void addVcard(Uri uri, boolean append) {
if (uri != null) {
int result = 0;
if (IS_APPEND_MEDIA && mWorkingMessage.hasAttachment()){
result = mWorkingMessage.addAttachment(WorkingMessage.VCARD, uri);
}else {
result = mWorkingMessage.setAttachment(WorkingMessage.VCARD, uri, append);
}
handleAddAttachmentError(result, R.string.type_vcard);
}
}
private void addVcard(Uri uri, boolean append,boolean isAppendMedia) {
if (uri != null) {
int result = 0;
if (isAppendMedia && mWorkingMessage.hasAttachment()){
result = mWorkingMessage.addAttachment(WorkingMessage.VCARD, uri);
}else {
result = mWorkingMessage.setAttachment(WorkingMessage.VCARD, uri, append);
}
handleAddAttachmentError(result, R.string.type_vcard);
}
}
private void addOtherFile(Uri uri, boolean append) {
if (uri != null) {
int result = 0;
if (mWorkingMessage.hasAttachment()){
result = mWorkingMessage.addAttachment(WorkingMessage.OTHER_FILE, uri);
}else {
result = mWorkingMessage.setAttachment(WorkingMessage.OTHER_FILE, uri, append);
}
handleAddAttachmentError(result, R.string.type_file);
}
}
private void addAudio(Uri uri, boolean append) {
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 begin======
int result = 0;
if (IS_APPEND_MEDIA && mWorkingMessage.hasAttachment()) {
result = mWorkingMessage.addAttachment(WorkingMessage.AUDIO, uri);
} else {
result = mWorkingMessage.setAttachment(WorkingMessage.AUDIO, uri, append);
}
// ======fixed CR<NEWMS00110179> by luning at 11-08-12 end======
handleAddAttachmentError(result, R.string.type_audio);
}
private boolean handleForwardedMessage() {
Intent intent = getIntent();
// If this is a forwarded message, it will have an Intent extra
// indicating so. If not, bail out.
if (intent == null || mWorkingMessage == null || mMsgListAdapter == null
|| intent.getBooleanExtra("forwarded_message", false) == false) {
return false;
}
Uri uri = intent.getParcelableExtra("msg_uri");
String nameAndnumber = "";
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (sp.getBoolean(MessagingPreferenceActivity.FORWARDING_NUMBER, true)) {
String senderNumber = intent.getStringExtra("sender_number");
Contact contact = Contact.get(senderNumber, false);
String text = mRecipientsEditor.getText().toString().trim();
int length = text.length();
if (length != 0 && text.charAt(length - 1) != ',') {
mRecipientsEditor.append(", ");
}
String name = contact.getName();
String number = contact.getNumber();
if (name.equals(number)) {
nameAndnumber = " <" + number + ">, ";
} else {
nameAndnumber = name + " <" + number + ">, ";
}
}
if (Log.isLoggable(LogTag.APP, Log.DEBUG)) {
log("" + uri);
}
if (uri != null) {
mWorkingMessage = WorkingMessage.load(this, uri, true);
if (mWorkingMessage == null) {
Toast.makeText(this, R.string.handle_forward_error, Toast.LENGTH_LONG);
return false;
}
mWorkingMessage.setSubject(intent.getStringExtra("subject"), false);
} else {
mWorkingMessage.setText(nameAndnumber+intent.getStringExtra("sms_body"));
}
// let's clear the message thread for forwarded messages
mMsgListAdapter.changeCursor(null);
return true;
}
private boolean handleSendIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras == null) {
return false;
}
final String mimeType = intent.getType();
String action = intent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
if (extras.containsKey(Intent.EXTRA_STREAM)) {
Uri uri = (Uri)extras.getParcelable(Intent.EXTRA_STREAM);
addAttachment(mimeType, uri, false);
return true;
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
mWorkingMessage.setText(extras.getString(Intent.EXTRA_TEXT));
return true;
}
}
else if ("android.intent.action.SEND_SIM".equals(action)) {
String cName = extras.getString("name");
String cNumber = extras.getString("number");
final ByteArrayOutputStream localStream = new ByteArrayOutputStream();
final VCardComposer composer = new VCardComposer(ComposeMessageActivity.this,
VCardConfig.VCARD_TYPE_DEFAULT, false);
composer.addHandler(composer.new HandlerForOutputStream(localStream));
// if (!composer.init(cName)) {
// Log.e(TAG, "Failed to init VCardComposer");
// return true;
// }
// if (!composer.createOneEntry(cName, cNumber)) {
// Log.e(TAG, "Failed to output a contact.");
// }
composer.terminate();
//fix for bug 4045 by phone_02, create the sim card Contacts and send
VCardBuilder builder = new VCardBuilder(VCardConfig.getVCardTypeFromString("default"));
ContentValues values = new ContentValues();
values.put(StructuredName.DISPLAY_NAME, cName);
ArrayList<ContentValues> list = new ArrayList<ContentValues>();
list.add(values);
builder.appendNameProperties(list);
values = new ContentValues();
values.put(Phone.NUMBER, cNumber);
list = new ArrayList<ContentValues>();
list.add(values);
builder.appendPhones(list);
//final byte[] byteData = localStream.toByteArray();
byte[] byteData = null;
try {
byteData = builder.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
Log.e("TAG", "UnsupportedEncodingException~~~",e1);
}
File f = new File("/data/data/com.android.mms/" + cName + ".vcf");
FileOutputStream fos = null;
try {
if (!f.exists()) {
f.createNewFile();
}
fos = new FileOutputStream(f);
fos.write(byteData);
Uri uri = Uri.fromFile(f);
addAttachment(mimeType, uri, false);
return true;
} catch (Exception e) {
Log.e(TAG, "send contact:" + e.toString());
Toast.makeText(ComposeMessageActivity.this, "send sim contact error",
Toast.LENGTH_LONG);
} finally {
try {
localStream.close();
fos.close();
} catch (Exception e) {
Log.e(TAG, "close stream failed" + e.toString());
}
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) &&
extras.containsKey(Intent.EXTRA_STREAM)) {
SlideshowModel slideShow = mWorkingMessage.getSlideshow();
final ArrayList<Parcelable> uris = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
int currentSlideCount = slideShow != null ? slideShow.size() : 0;
int importCount = uris.size();
if (importCount + currentSlideCount > SlideshowEditor.MAX_SLIDE_NUM) {
importCount = Math.min(SlideshowEditor.MAX_SLIDE_NUM - currentSlideCount,
importCount);
Toast.makeText(ComposeMessageActivity.this,
getString(R.string.too_many_attachments,
SlideshowEditor.MAX_SLIDE_NUM, importCount),
Toast.LENGTH_LONG).show();
}
// Attach all the pictures/videos off of the UI thread.
// Show a progress alert if adding all the slides hasn't finished
// within one second.
// Stash the runnable for showing it away so we can cancel
// it later if adding completes ahead of the deadline.
final AlertDialog dialog = new AlertDialog.Builder(ComposeMessageActivity.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.adding_attachments_title)
.setMessage(R.string.adding_attachments)
.create();
final Runnable showProgress = new Runnable() {
public void run() {
dialog.show();
}
};
// Schedule it for one second from now.
mAttachmentEditorHandler.postDelayed(showProgress, 1000);
final int numberToImport = importCount;
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < numberToImport; i++) {
Parcelable uri = uris.get(i);
addAttachment(mimeType, (Uri) uri, true);
}
// Cancel pending show of the progress alert if necessary.
mAttachmentEditorHandler.removeCallbacks(showProgress);
dialog.dismiss();
}
}, "addAttachment").start();
return true;
}
return false;
}
// mVideoUri will look like this: content://media/external/video/media
private static final String mVideoUri = Video.Media.getContentUri("external").toString();
// mImageUri will look like this: content://media/external/images/media
private static final String mImageUri = Images.Media.getContentUri("external").toString();
private void addAttachment(String type, Uri uri, boolean append) {
if (uri != null) {
// When we're handling Intent.ACTION_SEND_MULTIPLE, the passed in items can be
// videos, and/or images, and/or some other unknown types we don't handle. When
// a single attachment is "shared" the type will specify an image or video. When
// there are multiple types, the type passed in is "*/*". In that case, we've got
// to look at the uri to figure out if it is an image or video.
if (uri.getScheme().equals("file")) {
type = getSharedFileType(uri);
}
boolean wildcard = "*/*".equals(type);
if (type.startsWith("image/") || (wildcard && uri.toString().startsWith(mImageUri))) {
addImage(uri, append);
} else if (type.startsWith("video/") ||
(wildcard && uri.toString().startsWith(mVideoUri))) {
addVideo(uri, append);
} else if (type.equals("text/x-vcard")) {
is_vcard_adding = true;
mVcardProgressDialog = new ProgressDialog(this);
mVcardProgressDialog.setMessage(getString(R.string.on_progress));
mVcardProgressDialog.setIndeterminate(true);
mVcardProgressDialog.setCancelable(false);
mVcardProgressDialog.show();
mEventHandler = new VcardProgressHandler(getMainLooper());
Thread t = new myThread(uri, append,IS_APPEND_MEDIA);
t.start();
//addVcard(uri, append);
} else if (type.startsWith("audio/")) {// 20120229 bug 11791
addAudio(uri, append);
} else {
addOtherFile(uri, append);
}
// else {
//
// final Runnable showToast = new Runnable() {
// public void run() {
// Toast.makeText(ComposeMessageActivity.this,
// R.string.share_not_support_contentType, Toast.LENGTH_LONG).show();
// }
// };
// mAttachmentEditorHandler.postDelayed(showToast, 500);
//
// }
}
}
private String getSharedFileType(Uri uri) {
Log.d(TAG, "getSharedFileType -> The passed uri is " + uri);
String path = uri.getPath();
String contentType;
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String extension = MimeTypeMap.getFileExtensionFromUrl(path);
if (TextUtils.isEmpty(extension)) {
// getMimeTypeFromExtension() doesn't handle spaces in filenames nor can it handle
// urlEncoded strings. Let's try one last time at finding the extension.
int dotPos = path.lastIndexOf('.');
if (0 <= dotPos) {
extension = path.substring(dotPos + 1);
}
}
contentType = mimeTypeMap.getMimeTypeFromExtension(extension);
Log.d(TAG, "Shared file Content Type is: " + contentType);
return contentType;
}
private String getResourcesString(int id, String mediaName) {
Resources r = getResources();
return r.getString(id, mediaName);
}
private void drawBottomPanel() {
// Reset the counter for text editor.
resetCounter();
// ===== fixed CR<NEWMS00129480> by luning at 11-10-13 begin =====
// if (mWorkingMessage.hasSlideshow())
if ((mWorkingMessage.hasSlideshow() && !mWorkingMessage.getSlideshow()
.isSimpleSlide()) || ("true".equals(boxmsgFlg) && (OUTBOX.equals(boxType) || SENT.equals(boxType))))
// ===== fixed CR<NEWMS00129480> by luning at 11-10-13 end =====
{
if (!outboxEditMsgFlg) {
mBottomPanel.setVisibility(View.GONE);
mAttachmentEditor.requestFocus();
return;
}
}
mBottomPanel.setVisibility(View.VISIBLE);
CharSequence text = mWorkingMessage.getText();
// TextView.setTextKeepState() doesn't like null input.
if (text != null) {
mTextEditor.setTextKeepState(text);
} else {
mTextEditor.setText("");
}
}
private void drawTopPanel() {
showSubjectEditor(mWorkingMessage.hasSubject());
}
//==========================================================
// Interface methods
//==========================================================
public void onClick(View v) {
if ((v == mSendButton) && isPreparedForSending()) {
Log.d(TAG, "[sms]onClick send button mSmsReady[0]=" + mSmsReady[0]+ " mSmsReady[1]="+mSmsReady[1]);
confirmSendMessageIfNeeded();
// list.clear();/*delete for CR<NEWMS00135995> by luning at 11-11-04 */
}else if(v == mContactsSelectButton){
//modify by dory.zheng for NEWMS00120648 at 15-09 begin
displayContactsDialog();
// Intent intent = new Intent("com.android.contacts.MULTIOPERATELIST");
// startActivityForResult(intent, REQUESET_CODE_SELECT_CONTACTS);
//modify by dory.zheng for NEWMS00120648 at 15-09 end
}
}
//add by dory.zheng for NEWMS00120648 at 15-09 begin
private boolean simCardReady(){
Log.v(TAG, "getSimState = " + ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).getSimState());
if(TelephonyManager.SIM_STATE_READY == ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).getSimState()){
Log.v(TAG, "sim ready");
return true;
}else{
Toast.makeText(this, getString(R.string.sim_no_ready), Toast.LENGTH_SHORT).show();
return false;
}
}
private boolean simCardReady(int phoneId){
TelephonyManager telManager = (TelephonyManager) getSystemService(
PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, phoneId));
boolean hasSim = (null != telManager) ? telManager.hasIccCard() : false;
if (hasSim && telManager.getSimState() == TelephonyManager.SIM_STATE_READY) {
Log.v(TAG, "sim ready");
return true;
}else{
Toast.makeText(this, getString(R.string.sim_no_ready), Toast.LENGTH_SHORT).show();
return false;
}
}
private void displayContactsDialog() {
// Wrap our context to inflate list items using correct theme
final Context dialogContext = new ContextThemeWrapper(this, android.R.style.Theme_Light);
final Resources res = dialogContext.getResources();
final LayoutInflater dialogInflater = (LayoutInflater)dialogContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Adapter that shows a list of string resources
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = dialogInflater.inflate(android.R.layout.simple_list_item_1,
parent, false);
}
final String resString = this.getItem(position);
((TextView)convertView).setText(resString);
return convertView;
}
};
adapter.add(getString(R.string.group_all));
adapter.add(getString(R.string.group_phone));
if(MessageUtils.isMSMS){
// TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyManager telManager = (TelephonyManager) getSystemService(
PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, 0));
TelephonyManager telManager2 = (TelephonyManager) getSystemService(
PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, 1));
boolean hasSim1 = (null != telManager) ? telManager.hasIccCard() : false;
boolean hasSim2 = (null != telManager2) ? telManager2.hasIccCard() : false;
if (hasSim1 && telManager.getSimState() == TelephonyManager.SIM_STATE_READY) {
adapter.add(getString(R.string.group_sim1));
}
if (hasSim2 && telManager2.getSimState() == TelephonyManager.SIM_STATE_READY) {
adapter.add(getString(R.string.group_sim2));
}
}else{
if(TelephonyManager.SIM_STATE_READY == ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).getSimState()){
adapter.add(getString(R.string.group_sim));
}
}
final Map<Integer, String> dividedNameMap = new HashMap<Integer, String>();
Cursor cursor = this.getContentResolver().query(DIVIDED_GROUP_URI,
null, null, null, null);
String tmp;
int id ;
while(cursor.moveToNext()){
tmp = cursor.getString(cursor.getColumnIndexOrThrow("divided_name"));
id = cursor.getInt(cursor.getColumnIndexOrThrow(BaseColumns._ID));
//for bugzilla 13822
if(/*!TextUtils.isEmpty(tmp && */id < 4 && id > -1){
tmp = getDeafaultGroupName(id);
}
dividedNameMap.put(id, tmp);
adapter.add(tmp);
}
if (cursor != null) {
cursor.close();
}
final DialogInterface.OnClickListener clickListener =
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
// // for group
final String resString = adapter.getItem(which);
int mContactsGroupNameId = -1;
Intent intent = new Intent("com.android.contacts.MULTIOPERATELIST");
if(dividedNameMap.size() > 0){
for(Entry<Integer, String> tmp : dividedNameMap.entrySet()){
if(tmp.getValue() == resString){
mContactsGroupNameId = tmp.getKey();
}
}
}
if (resString == getString(R.string.group_all)) {
intent.putExtra("type", GROUP_ALL);
} else if (resString == getString(R.string.group_phone)) {
intent.putExtra("type", GROUP_PHONE);
} else if (resString == getString(R.string.group_sim)) {
intent.putExtra("type", GROUP_SIM);
if(!simCardReady()){
return;
}
}else if(resString == getString(R.string.group_sim1)) {
intent.putExtra("type", GROUP_SIM1);
if(!simCardReady(0)){
return;
}
}else if(resString == getString(R.string.group_sim2)){
intent.putExtra("type", GROUP_SIM2);
if(!simCardReady(1)){
return;
}
}else {
Log.d(TAG,"Unexpected resource.");
}
if(mContactsGroupNameId != -1){
intent.putExtra("groupNameId", mContactsGroupNameId);
}
intent.putExtra("group",MODE_PICK);
intent.putExtra("limit", RECIPIENTS_MAX_MUBER);
if (mRecipientsEditor.getRecipientCount() > 0) {
mWorkingMessage.discard();
}
startActivityForResult(intent, REQUESET_CODE_SELECT_CONTACTS);
}
};
new AlertDialog.Builder(this)
.setTitle(R.string.select_contacts_group)
.setNegativeButton(android.R.string.cancel, null)
.setSingleChoiceItems(adapter, -1, clickListener)
.show();
}
//add by dory.zheng for NEWMS00120648 at 15-09 begin
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event != null) {
// if shift key is down, then we want to insert the '\n' char in the TextView;
// otherwise, the default action is to send the message.
if (!event.isShiftPressed() &&
event.getAction() == KeyEvent.ACTION_DOWN/*fixed CR<NEWMS00142440> by luning at 2011.11.19*/) {
if (isPreparedForSending()) {
confirmSendMessageIfNeeded();
}
return true;
}
return false;
}
if (isPreparedForSending()) {
confirmSendMessageIfNeeded();
}
return true;
}
/**
* @param s input string to judge
* @return if string contained chinese character will return true, else
*/
private boolean isContainChinese(CharSequence s){
for(int i = 0; i < s.length(); i++){
if(s.toString().codePointAt(i) > 128){
return true;
}
}
return false;
}
private TextWatcher mTextEditorWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// This is a workaround for bug 1609057. Since onUserInteraction() is
// not called when the user touches the soft keyboard, we pretend it was
// called when textfields changes. This should be removed when the bug
// is fixed.
onUserInteraction();
/*fixed CR<NEWMS00148018> by luning at 2011.12.13 begin*/
if(s.length() > MmsConfig.getmMaxTextLength()) {
Toast.makeText(ComposeMessageActivity.this,
getString(R.string.exceed_text_length_limitation), Toast.LENGTH_SHORT)
.show();
s = s.subSequence(0, MmsConfig.getmMaxTextLength());
mTextEditor.setText(s);
Editable editable = mTextEditor.getEditableText();
Selection.setSelection(editable, editable.length());
}
checkMessageSize(s,MmsConfig.getmMaxTextLength(),getTextOldLen());
if(mTxtCompareRst != TextCompareResult.NOEXCEED_ANY_SIZE) {
if(mTxtCompareRst == TextCompareResult.EXCEED_MAX_MMS_SIZE) {
showErDialog();
s = s.subSequence(0, mTxtLength);
mTextEditor.setText(s);
Editable editable = mTextEditor.getEditableText();
Selection.setSelection(editable, editable.length());
} else if(mTxtCompareRst == TextCompareResult.EXCEED_ORGINAL_MAX_MMS_SIZE) {
if(s.length() > 0) {
s = "";
mTextEditor.setText(s);
showErDialog();
}
}
}
/*fixed CR<NEWMS00148018> by luning at 2011.12.13 end*/
updateText(s);
mWorkingMessage.setText(s);
updateSendButtonState();
updateCounter(s, start, before, count);
mAttachmentEditor.update(mWorkingMessage);
//ensureCorrectButtonHeight();
//yeezone:jinwei set edited message count
if(FeatureSwitch.COMPOSE_MESSAGE_TIP_SUPPORT){
if(s.length() == 0){
//mTitleRight.setText(LIMITED_MESSAGE_MAX_COUNT + "/" + 1);
return;
}//delete for wrong message count 20110722
}
}
public void afterTextChanged(Editable s) {
}
};
/**
* Ensures that if the text edit box extends past two lines then the
* button will be shifted up to allow enough space for the character
* counter string to be placed beneath it.
*/
private void ensureCorrectButtonHeight() {
int currentTextLines = mTextEditor.getLineCount();
if (currentTextLines <= 2) {
mTextCounter.setVisibility(View.GONE);
}
else if (currentTextLines > 2 && mTextCounter.getVisibility() == View.GONE) {
// Making the counter invisible ensures that it is used to correctly
// calculate the position of the send button even if we choose not to
// display the text.
mTextCounter.setVisibility(View.INVISIBLE);
}
}
private TextWatcher mSubjectEditorWatcher = new TextWatcher() {
int length = 0;
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
/* fixed CR<NEWMS00150391> by luning at 2011.12.14 begin*/
if(null != s){
length = s.length();
}
/* fixed CR<NEWMS00150391> by luning at 2011.12.14 end*/
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
/* fixed CR<NEWMS00150391> by luning at 2011.12.14 begin*/
/* fixed CR<NEWMS00150391> by luning at 2011.12.14 end*/
if(s.length() > MmsConfig.getmMaxSubjectSize()) {
Toast.makeText(ComposeMessageActivity.this,
getString(R.string.exceed_text_length_limitation), Toast.LENGTH_SHORT)
.show();
s = s.subSequence(0, MmsConfig.getmMaxSubjectSize());
mSubjectTextEditor.setText(s);
Editable editable = mSubjectTextEditor.getEditableText();
Selection.setSelection(editable, editable.length());
}
checkMessageSize(s,MmsConfig.getmMaxSubjectSize(),mWorkingMessage.getSubjectLength());
if(mTxtCompareRst != TextCompareResult.NOEXCEED_ANY_SIZE) {
if(mTxtCompareRst == TextCompareResult.EXCEED_MAX_MMS_SIZE) {
showErDialog();
s = s.subSequence(0, mTxtLength);
mSubjectTextEditor.setText(s);
Editable editable = mSubjectTextEditor.getEditableText();
Selection.setSelection(editable, editable.length());
} else if(mTxtCompareRst == TextCompareResult.EXCEED_ORGINAL_MAX_MMS_SIZE) {
if(s.length() > 0) {
s = "";
mSubjectTextEditor.setText(s);
showErDialog();
}
}
}
mWorkingMessage.setSubject(s, true);
mAttachmentEditor.update(mWorkingMessage);
}
public void afterTextChanged(Editable s) { }
};
//==========================================================
// Private methods
//==========================================================
/**
* Initialize all UI elements from resources.
*/
private void initResourceRefs() {
if(FeatureSwitch.COMPOSE_MESSAGE_TIP_SUPPORT){
mTitleLeft = (TextView) findViewById(R.id.left_text);
mTitleRight = (TextView) findViewById(R.id.right_text);
}
mMsgListView = (MessageListView) findViewById(R.id.history);
mMsgListView.setDivider(null); // no divider so we look like IM conversation.
mBottomPanel = findViewById(R.id.bottom_panel);
mTextEditor = (EditText) findViewById(R.id.embedded_text_editor);
//mTextEditor.setOnEditorActionListener(this);
mTextEditor.addTextChangedListener(mTextEditorWatcher);
mTextCounter = (TextView) findViewById(R.id.text_counter);
mSendButton = (Button) findViewById(R.id.send_button);
mSendButton.setOnClickListener(this);
mContactsSelectButton = (Button) findViewById(R.id.contacts_import);
mContactsSelectButton.setOnClickListener(this);
mTopPanel = findViewById(R.id.recipients_subject_linear);
mTopPanel.setFocusable(false);
mAttachmentEditor = (AttachmentEditor) findViewById(R.id.attachment_editor);
mAttachmentEditor.setHandler(mAttachmentEditorHandler);
}
private void confirmDeleteDialog(OnClickListener listener, boolean locked) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(locked ? R.string.confirm_dialog_locked_title :
R.string.confirm_dialog_title);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setCancelable(true);
builder.setMessage(locked ? R.string.confirm_delete_locked_message :
R.string.confirm_delete_message);
builder.setPositiveButton(R.string.delete, listener);
builder.setNegativeButton(R.string.no, null);
builder.show();
}
void undeliveredMessageDialog(long date) {
String body;
LinearLayout dialog = (LinearLayout) LayoutInflater.from(this).inflate(
R.layout.retry_sending_dialog, null);
if (date >= 0) {
body = getString(R.string.undelivered_msg_dialog_body,
MessageUtils.formatTimeStampString(this, date));
} else {
// FIXME: we can not get sms retry time.
body = getString(R.string.undelivered_sms_dialog_body);
}
((TextView) dialog.findViewById(R.id.body_text_view)).setText(body);
Toast undeliveredDialog = new Toast(this);
undeliveredDialog.setView(dialog);
undeliveredDialog.setDuration(Toast.LENGTH_LONG);
undeliveredDialog.show();
}
private void startMsgListQuery() {
// for bug 9064
// if (mConversation.getRecipients().size() > 0) {/* fixed CR<NEWMS00143653> by luning at 2011.11.23*/
// mConversation.ensureThreadId();// ensure threadID first
// }
Uri conversationUri = null;
String boxTypeInt = "";
if (INBOX.equals(boxType)) {
boxTypeInt = "1";
} else if (OUTBOX.equals(boxType)) {
boxTypeInt = "4";
} else if (SENT.equals(boxType)) {
boxTypeInt = "2";
} else if (DRAFTS.equals(boxType)) {
boxTypeInt = "3";
}
if ("true".equals(boxmsgFlg) && !isLongPressSendFlg && !notificationFlg) {
conversationUri = Uri.parse("content://mms-sms/messageview/"
+ boxmsgThreadId + "/" + boxmsgMsgId + "/" + boxTypeInt);
} else {
conversationUri = mConversation.getUri();
}
if (conversationUri == null) {
return;
}
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("for " + conversationUri);
}
// Cancel any pending queries
mBackgroundQueryHandler.cancelOperation(MESSAGE_LIST_QUERY_TOKEN);
try {
// Kick off the new query
mBackgroundQueryHandler.startQuery(
MESSAGE_LIST_QUERY_TOKEN, null, conversationUri,
PROJECTION, null, null, null);
} catch (SQLiteException e) {
SqliteWrapper.checkSQLiteException(this, e);
}
}
private void initMessageList() {
if (mMsgListAdapter != null) {
return;
}
String highlightString = getIntent().getStringExtra("highlight");
Pattern highlight = highlightString == null
? null
: Pattern.compile("\\b" + Pattern.quote(highlightString), Pattern.CASE_INSENSITIVE);
// Initialize the list adapter with a null cursor.
mMsgListAdapter = new MessageListAdapter(this, null, mMsgListView, true, highlight);
mMsgListAdapter.setOnDataSetChangedListener(mDataSetChangedListener);
mMsgListAdapter.setMsgListItemHandler(mMessageListItemHandler);
mMsgListView.setAdapter(mMsgListAdapter);
mMsgListView.setItemsCanFocus(false);
mMsgListView.setVisibility(View.VISIBLE);
mMsgListView.setOnCreateContextMenuListener(mMsgListMenuCreateListener);
mMsgListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view != null) {
((MessageListItem) view).onMessageListItemClick();
}
}
});
//new ZoomViewUtil<View>(mMsgListView);
mZoom = new ZoomViewUtil(this);
mZoom.setView(mMsgListView,mMsgListAdapter.getTextSize());
}
public void onTextResize(float size) {
mMsgListAdapter.setTextSize(size);
}
private void loadDraft() {
if (mWorkingMessage != null && mWorkingMessage.isWorthSaving()) {
Log.w(TAG, "called with non-empty working message");
return;
}
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("call WorkingMessage.loadDraft");
}
mWorkingMessage = WorkingMessage.loadDraft(this, mConversation);
}
private void saveDraft() {
// TODO: Do something better here. Maybe make discard() legal
// to call twice and make isEmpty() return true if discarded
// so it is caught in the clause above this one?
if (mWorkingMessage.isDiscarded()) {
return;
}
if (!mWaitingForSubActivity && !mWorkingMessage.isWorthSaving()) {
if (LogTag.VERBOSE || DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("not worth saving, discard WorkingMessage and bail");
}
mWorkingMessage.discard();
return;
}
try{
mWorkingMessage.saveDraft();
}catch(ExceedMessageSizeException e){
Log.d(TAG, "Do saveDraft hanppend ExceedMessageSizeException :"+e.toString(), e);
String title = this.getResources().getString(R.string.exceed_message_size_limitation);
String message = this.getResources().getString(R.string.exceed_message_size_limitation);
MessageUtils.showErrorDialog(this, title, message);
return;
}
if (mToastForDraftSave) {
Toast.makeText(this, R.string.message_saved_as_draft,
Toast.LENGTH_SHORT).show();
}
}
private boolean isPreparedForSending() {
int recipientCount = recipientCount();
return recipientCount > 0 && recipientCount <= MmsConfig.getRecipientLimit() &&
(mWorkingMessage.hasAttachment() || mWorkingMessage.hasText());
}
private int recipientCount() {
int recipientCount;
// To avoid creating a bunch of invalid Contacts when the recipients
// editor is in flux, we keep the recipients list empty. So if the
// recipients editor is showing, see if there is anything in it rather
// than consulting the empty recipient list.
if (isRecipientsEditorVisible()) {
recipientCount = mRecipientsEditor.getRecipientCount();
} else {
recipientCount = getRecipients().size();
}
return recipientCount;
}
private void sendMessage(boolean bCheckEcmMode) {
if (bCheckEcmMode) {
// TODO: expose this in telephony layer for SDK build
String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
if (Boolean.parseBoolean(inEcm)) {
try {
startActivityForResult(
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
REQUEST_CODE_ECM_EXIT_DIALOG);
return;
} catch (ActivityNotFoundException e) {
// continue to send message
Log.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e);
}
}
}
// sunway: get phoneId
final String launchMode = getLaunchMode(MMS_LAUNCH_MODE_PATH);
if (!mSendingMessage) {
if (LogTag.SEVERE_WARNING) {
String sendingRecipients = mConversation.getRecipients().serialize();
if (!sendingRecipients.equals(mDebugRecipients)) {
String workingRecipients = mWorkingMessage.getWorkingRecipients();
if (!mDebugRecipients.equals(workingRecipients)) {
LogTag.warnPossibleRecipientMismatch("ComposeMessageActivity.sendMessage recipients in " +
"window: \"" +
mDebugRecipients + "\" differ from recipients from conv: \"" +
sendingRecipients + "\" and working recipients: " +
workingRecipients, this);
}
}
}
int phoneId = TelephonyManager.getDefaultSim(this,TelephonyManager.MODE_MMS);
if (phoneId>=0) {
mWorkingMessage.setPhoneId(phoneId);
// send can change the recipients. Make sure we remove the listeners first and then add
// them back once the recipient list has settled.
removeRecipientsListeners();
if(mWorkingMessage.send(mDebugRecipients)){
mSentMessage = true;
mSendingMessage = true;
addRecipientsListeners();
}else{
mSendingMessage = false;
}
} else {
mSimChooserDialg.setListener(new SimChooserDialog.OnSimPickedListener() {
public void onSimPicked(int phoneId) {
if (phoneId==-1) {
return;
}
mWorkingMessage.setPhoneId(phoneId);
// send can change the recipients. Make sure we remove the listeners first and then add
// them back once the recipient list has settled.
removeRecipientsListeners();
if(mWorkingMessage.send(mDebugRecipients)){
mSentMessage = true;
mSendingMessage = true;
addRecipientsListeners();
}else{
mSendingMessage = false;
}
if (mExitOnSent || "folder".equals(launchMode)) {
ComposeMessageActivity.this.finish();
}
}
});
mSimChooserDialg.show();
return;
}
// // send can change the recipients. Make sure we remove the listeners first and then add
// // them back once the recipient list has settled.
// removeRecipientsListeners();
// mWorkingMessage.send(mDebugRecipients);
// mSentMessage = true;
// mSendingMessage = true;
// addRecipientsListeners();
}
// But bail out if we are supposed to exit after the message is sent.
if (mExitOnSent || "folder".equals(launchMode)) {
finish();
}
}
private void resetMessage() {
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("");
}
// Make the attachment editor hide its view.
mAttachmentEditor.hideView();
// Hide the subject editor.
showSubjectEditor(false);
// Focus to the text editor.
mTextEditor.requestFocus();
// We have to remove the text change listener while the text editor gets cleared and
// we subsequently turn the message back into SMS. When the listener is listening while
// doing the clearing, it's fighting to update its counts and itself try and turn
// the message one way or the other.
mTextEditor.removeTextChangedListener(mTextEditorWatcher);
// Clear the text box.
TextKeyListener.clear(mTextEditor.getText());
mWorkingMessage = WorkingMessage.createEmpty(this);
mWorkingMessage.setConversation(mConversation);
hideRecipientEditor();
drawBottomPanel();
// "Or not", in this case.
updateSendButtonState();
// Our changes are done. Let the listener respond to text changes once again.
mTextEditor.addTextChangedListener(mTextEditorWatcher);
// Close the soft on-screen keyboard if we're in landscape mode so the user can see the
// conversation.
if (mIsLandscape) {
InputMethodManager inputMethodManager =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(mTextEditor.getWindowToken(), 0);
}
mLastRecipientCount = 0;
mSendingMessage = false;
//jinwei
if(FeatureSwitch.COMPOSE_MESSAGE_TIP_SUPPORT){
//mTitleRight.setText(LIMITED_MESSAGE_MAX_COUNT + "/" + 1);
}
}
private void updateSendButtonState() {
boolean enable = false;
if (isPreparedForSending()) {
enable = true;//fix for bug 8868
// When the type of attachment is slideshow, we should
// also hide the 'Send' button since the slideshow view
// already has a 'Send' button embedded.
if (!mWorkingMessage.hasSlideshow()) {
enable = true;
} else {
mAttachmentEditor.setCanSend(true);
}
} else if (null != mAttachmentEditor){
mAttachmentEditor.setCanSend(false);
}
setSendButtonText(mWorkingMessage.requiresMms());
mSendButton.setEnabled(enable);
mSendButton.setFocusable(enable);
}
private long getMessageDate(Uri uri) {
if (uri != null) {
Cursor cursor = SqliteWrapper.query(this, mContentResolver,
uri, new String[] { Mms.DATE }, null, null, null);
if (cursor != null) {
try {
if ((cursor.getCount() == 1) && cursor.moveToFirst()) {
return cursor.getLong(0) * 1000L;
}
} finally {
cursor.close();
}
}
}
return NO_DATE_FOR_DIALOG;
}
private void initActivityState(Bundle bundle, Intent intent, Bundle bundle2) {
if (bundle != null) {
String recipients = bundle.getString("recipients");
if (LogTag.VERBOSE) log("get mConversation by recipients " + recipients);
mConversation = Conversation.get(this,
ContactList.getByNumbers(recipients,
false /* don't block */, true /* replace number */), false);
addRecipientsListeners();
mExitOnSent = bundle.getBoolean("exit_on_sent", false);
mWorkingMessage.readStateFromBundle(bundle);
return;
}
// If we have been passed a thread_id, use that to find our conversation.
if (bundle2 != null) {
boxmsgThreadId = bundle2.getString("boxmsgThreadId");
}
long threadId;
if (boxmsgThreadId != null && !"".equals(boxmsgThreadId) && !isLongPressSendFlg) {
threadId = Long.parseLong(boxmsgThreadId);
} else {
threadId = intent.getLongExtra("thread_id", 0);
}
if (threadId > 0) {
if (LogTag.VERBOSE) log("get mConversation by threadId " + threadId);
mConversation = Conversation.get(this, threadId, false);
} else {
Uri intentData = intent.getData();
// mCreate = intent.getBooleanExtra("create", false);
if (intentData != null) {
// try to get a conversation based on the data URI passed to our intent.
if (LogTag.VERBOSE) log("get mConversation by intentData " + intentData);
mConversation = Conversation.get(this, intentData, false);
// ===== fixed CR<NEWMS00120798> by luning at 2011.11.08 begin =====
String scheme = intentData.getScheme();/*send contact*/
if(scheme != null && scheme.equals("mms")){
String sharePath = intent.getStringExtra("share_contact_uri");
String name = intent.getStringExtra("name");
String detail = intent.getStringExtra("detail");
AssetFileDescriptor fd = null;
FileInputStream fis = null;
Uri vcardUri = null;
try {
fd = mContentResolver.openAssetFileDescriptor(Uri
.parse(sharePath), "rw");
fis = fd.createInputStream();
File f = new File("/data/data/com.android.mms/" + name
+ ".vcf");
if (!f.exists()) {
f.createNewFile();
}
if (!FileUtils.copyToFile(fis, f)) {
throw new Exception();
}
vcardUri = Uri.fromFile(f);
if (null != vcardUri) {
// VcardModel vcardModel = new VcardModel(this,
// ContentType.TEXT_VCARD, name, vcardUri);?????????????
// vcardModel.setDetail(detail);
// mWorkingMessage.addVcard(vcardModel);??
this.addAttachment("text/x-vcard", vcardUri, false);//fix for bug 10852
}
} catch (Exception e) {
Log.e(TAG, "send contact:" + e.toString());
Toast.makeText(ComposeMessageActivity.this, "send sim contact error",
Toast.LENGTH_LONG);
} finally {
try {
fis.close();
fd.close();
} catch (Exception e) {
Log.e(TAG, "close stream failed" + e.toString());
}
}
}
// ===== fixed CR<NEWMS00120798> by luning at 2011.11.08 end =====
} else {
// special intent extra parameter to specify the address
String address = intent.getStringExtra("address");
if (!TextUtils.isEmpty(address)) {
if (LogTag.VERBOSE) log("get mConversation by address " + address);
mConversation = Conversation.get(this, ContactList.getByNumbers(address,
false /* don't block */, true /* replace number */), false);
} else {
if (LogTag.VERBOSE) log("create new conversation");
mConversation = Conversation.createNew(this);
}
}
}
addRecipientsListeners();
mExitOnSent = intent.getBooleanExtra("exit_on_sent", false);
if (intent.hasExtra("sms_body")) {
mWorkingMessage.setText(intent.getStringExtra("sms_body"));
}
mWorkingMessage.setSubject(intent.getStringExtra("subject"), false);
}
private void initFocus() {
if (!mIsKeyboardOpen) {
return;
}
// If the recipients editor is visible, there is nothing in it,
// and the text editor is not already focused, focus the
// recipients editor.
if (isRecipientsEditorVisible()
&& TextUtils.isEmpty(mRecipientsEditor.getText())
&& !mTextEditor.isFocused()) {
mRecipientsEditor.requestFocus();
return;
}
// If we decided not to focus the recipients editor, focus the text editor.
mTextEditor.requestFocus();
}
private MessageListAdapter.OnDataSetChangedListener
mDataSetChangedListener = new MessageListAdapter.OnDataSetChangedListener() {
public void onDataSetChanged(MessageListAdapter adapter) {
mPossiblePendingNotification = true;
}
public void onContentChanged(MessageListAdapter adapter) {
// for bug 10942
// When the cursor changes, in the context menu MessageItems has invalid. So close it.
ComposeMessageActivity.this.closeContextMenu();
startMsgListQuery();
}
};
private void checkPendingNotification() {
if (mPossiblePendingNotification && hasWindowFocus()) {
Intent intent = getIntent();
Bundle checkbundle = intent.getExtras();
if (checkbundle != null) {
boxmsgFlg = checkbundle.getString("boxmsgFlg");
boxmsgThreadId = checkbundle.getString("boxmsgThreadId");
boxmsgMsgId = checkbundle.getString("boxmsgMsgId");
}
mConversation.markAsRead(boxmsgFlg, boxmsgThreadId, boxmsgMsgId);
mPossiblePendingNotification = false;
}
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch(token) {
case MESSAGE_LIST_QUERY_TOKEN:
if ( ComposeMessageActivity.this.isFinishing() ) {
Log.d(TAG,"onQueryComplete token:MESSAGE_LIST_QUERY_TOKEN -> isFinishing");
return;
}
if(mCursor != null){
mCursor.close();
mCursor = null;
}
int newSelectionPos = -1;
long targetMsgId = getIntent().getLongExtra("select_id", -1);
if (targetMsgId != -1) {
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
long msgId = cursor.getLong(COLUMN_ID);
if (msgId == targetMsgId ) {
newSelectionPos = cursor.getPosition();
break;
}
}
}
mCursor = cursor;
if(mMsgListAdapter != null){
mMsgListAdapter.changeCursor(cursor);
}
if (newSelectionPos != -1) {
mMsgListView.setSelection(newSelectionPos);
}
// Once we have completed the query for the message history, if
// there is nothing in the cursor and we are not composing a new
// message, we must be editing a draft in a new conversation (unless
// mSentMessage is true).
// Show the recipients editor to give the user a chance to add
// more people before the conversation begins.
if (cursor != null && cursor.getCount() == 0 && !isRecipientsEditorVisible() && !mSentMessage) {
if ((INBOX.equals(boxType) || OUTBOX.equals(boxType) || SENT.equals(boxType)) && !outboxEditMsgFlg && !isLongPressSendFlg) {
finish();
} else if(OUTBOX.equals(boxType) && outboxEditMsgFlg) {
initRecipientsEditor();
//outboxEditMsgFlg = false;
} else {
initRecipientsEditor();
}
}
isLongPressSendFlg = false;
// FIXME: freshing layout changes the focused view to an unexpected
// one, set it back to TextEditor forcely.
mTextEditor.requestFocus();
mConversation.blockMarkAsRead(false);
return;
case ConversationList.HAVE_LOCKED_MESSAGES_TOKEN:
long threadId = (Long)cookie;
ConversationList.confirmDeleteThreadDialog(
new ConversationList.DeleteThreadListener(threadId,
mBackgroundQueryHandler, ComposeMessageActivity.this),
threadId == -1,
cursor != null && cursor.getCount() > 0,
ComposeMessageActivity.this);
if ( cursor != null ) {
cursor.close();
}
break;
}
}
@Override
protected void onDeleteComplete(int token, Object cookie, int result) {
switch(token) {
case DELETE_MESSAGE_TOKEN:
case ConversationList.DELETE_CONVERSATION_TOKEN:
// Update the notification for new messages since they
// may be deleted.
MessagingNotification.nonBlockingUpdateNewMessageIndicator(
ComposeMessageActivity.this, false, false);
// Update the notification for failed messages since they
// may be deleted.
updateSendFailedNotification();
break;
}
if ((mMsgListAdapter.getCount() == 1 && !mWorkingMessage.hasText()) || INBOX.equals(boxType) || OUTBOX.equals(boxType) || SENT.equals(boxType)) {
finish();
}
// If we're deleting the whole conversation, throw away
// our current working message and bail.
if (token == ConversationList.DELETE_CONVERSATION_TOKEN) {
mWorkingMessage.discard();
Conversation.init(ComposeMessageActivity.this, false);
finish();
}
}
}
private void showSmileyDialog() {
if (mSmileyDialog == null) {
int[] icons = SmileyParser.DEFAULT_SMILEY_RES_IDS;
String[] names = getResources().getStringArray(
SmileyParser.DEFAULT_SMILEY_NAMES);
final String[] texts = getResources().getStringArray(
SmileyParser.DEFAULT_SMILEY_TEXTS);
final int N = names.length;
List<Map<String, ?>> entries = new ArrayList<Map<String, ?>>();
for (int i = 0; i < N; i++) {
// We might have different ASCII for the same icon, skip it if
// the icon is already added.
boolean added = false;
for (int j = 0; j < i; j++) {
if (icons[i] == icons[j]) {
added = true;
break;
}
}
if (!added) {
HashMap<String, Object> entry = new HashMap<String, Object>();
entry. put("icon", icons[i]);
entry. put("name", names[i]);
entry.put("text", texts[i]);
entries.add(entry);
}
}
final SimpleAdapter a = new SimpleAdapter(
this,
entries,
R.layout.smiley_menu_item,
new String[] {"icon", "name", "text"},
new int[] {R.id.smiley_icon, R.id.smiley_name, R.id.smiley_text});
SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() {
public boolean setViewValue(View view, Object data, String textRepresentation) {
if (view instanceof ImageView) {
Drawable img = getResources().getDrawable((Integer)data);
((ImageView)view).setImageDrawable(img);
return true;
}
return false;
}
};
a.setViewBinder(viewBinder);
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(getString(R.string.menu_insert_smiley));
b.setCancelable(true);
b.setAdapter(a, new DialogInterface.OnClickListener() {
@SuppressWarnings("unchecked")
public final void onClick(DialogInterface dialog, int which) {
HashMap<String, Object> item = (HashMap<String, Object>) a.getItem(which);
mTextEditor.append((String)item.get("text"));
dialog.dismiss();
}
});
mSmileyDialog = b.create();
}
mSmileyDialog.show();
}
public void onUpdate(final Contact updated) {
// Using an existing handler for the post, rather than conjuring up a new one.
mMessageListItemHandler.post(new Runnable() {
public void run() {
ContactList recipients = isRecipientsEditorVisible() ?
mRecipientsEditor.constructContactsFromInput() : getRecipients();
if (DEBUG || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("[CMA] onUpdate contact updated: " + updated);
log("[CMA] onUpdate recipients: " + recipients);
}
updateTitle(recipients);
// The contact information for one (or more) of the recipients has changed.
// Rebuild the message list so each MessageItem will get the last contact info.
if (recipients != null && recipients.size() > 0) {
String number = recipients.get(0).getNumber();
MessageListAdapter.mContact = TextUtils.isEmpty(number) ? "" : Contact.get(number, false).getName();
}
ComposeMessageActivity.this.mMsgListAdapter.notifyDataSetChanged();
if (mRecipientsEditor != null) {
mRecipientsEditor.populate(recipients);
}
}
});
}
private void addRecipientsListeners() {
Contact.addListener(this);
}
private void removeRecipientsListeners() {
Contact.removeListener(this);
}
public static Intent createIntent(Context context, long threadId) {
Intent intent = new Intent(context, ComposeMessageActivity.class);
if (threadId > 0) {
intent.setData(Conversation.getUri(threadId));
}
return intent;
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(TelephonyIntents.ACTION_IS_SIM_SMS_READY) ||action.equals(PhoneFactory.getAction(TelephonyIntents.ACTION_IS_SIM_SMS_READY,0))) {
mSmsReady[0] = intent.getBooleanExtra("isReady", false);
Log.d(TAG, "[sms]onReceive ACTION_IS_SIM_SMS_READY mSmsReady[0]=" + mSmsReady[0]);
}
else if (action.equals(TelephonyIntents.ACTION_IS_SIM_SMS_READY1)) {
mSmsReady[1] = intent.getBooleanExtra("isReady", false);
Log.d(TAG, "[sms]onReceive ACTION_IS_SIM_SMS_READY1 mSmsReady[1]=" + mSmsReady[1]);
}
//===== fixed CR<NEWMS00127040> by luning at 11-10-07 begin =====
else if (action.equals("sendMmsReadReport")) {
Log.d(TAG, "ComposeMessageActivity receiver sendMmsReadReport action");
HashMap<String, String> map = (HashMap<String, String>) intent
.getSerializableExtra("getMmsReadReportData");
if (map != null && map.size() > 0) {
MessageUtils.handleReadReport(context, map,
PduHeaders.READ_STATUS_READ, null);
}
}
//===== fixed CR<NEWMS00127040> by luning at 11-10-07 end =====
Log.d(TAG, "[sms]onReceive ACTION_IS_SIM_SMS_READY mSmsReady[0]=" + mSmsReady[0]);
Log.d(TAG, "[sms]onReceive ACTION_IS_SIM_SMS_READY1 mSmsReady[1]=" + mSmsReady[1]);
}
};
private String getBody(Uri uri) {
if (uri == null) {
return null;
}
String urlStr = uri.getSchemeSpecificPart();
if (!urlStr.contains("?")) {
return null;
}
urlStr = urlStr.substring(urlStr.indexOf('?') + 1);
String[] params = urlStr.split("&");
for (String p : params) {
if (p.startsWith("body=")) {
try {
return URLDecoder.decode(p.substring(5), "UTF-8");
} catch (UnsupportedEncodingException e) { }
}
}
return null;
}
private String getLaunchMode(String filename) {
String launchMode = "";
try {
File mFile= new File(filename);
if (mFile.exists()) {
FileInputStream is = new FileInputStream(filename);
int length = is.available();
byte buffer[] = new byte[length];
is.read(buffer);
launchMode = EncodingUtils.getString(buffer, "UTF-8");
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return launchMode;
}
public void showErDialog() {
runOnUiThread(new Runnable() {
public void run() {
String title = ComposeMessageActivity.this.getResources().getString(R.string.exceed_message_size_limitation);
String message = ComposeMessageActivity.this.getResources().getString(R.string.exceed_message_size_limitation);
MessageUtils.showErrorDialog(ComposeMessageActivity.this, title, message);
}
});
}
public int getTextOldLen() {
SlideshowModel slideShow = null;
SlideModel slide = null;
TextModel text = null;
mWorkingMessage.initTextToSlideshow();
slideShow = mWorkingMessage.getSlideshow();
if (slideShow != null) {
slide = slideShow.get(0);
if(slide != null) {
text = slide.getText();
if(text != null)
return text.getMediaSize();
}
}
return 0;
}
public void updateText(CharSequence s) {
SlideshowModel slideShow = null;
SlideModel slide = null;
TextModel text = null;
mWorkingMessage.initTextToSlideshow();
slideShow = mWorkingMessage.getSlideshow();
if (slideShow != null) {
slide = slideShow.get(0);
if(slide != null) {
text = slide.getText();
if(text != null) {
slide.updateText(s.toString());
}
}
}
}
public int CutByteToMaxLength(byte[] data,int maxByteLen){
int datalen,finallen;
byte i,j;
byte b;
boolean found = false;
int[][] headbyte_utf8={{0x80,0},{0xE0,0xC0},{0xF0,0xE0},{0xF8,0xF0},{0xFC,0xF8},{0xFE,0xFC}};
i= j = 0;
datalen = data.length;
finallen = maxByteLen;
while(i<headbyte_utf8.length && i<maxByteLen) {
b = data[maxByteLen-1-i];
for(j=0;j<headbyte_utf8.length;j++) {
if((b & headbyte_utf8[j][0]) == headbyte_utf8[j][1]) {
if(i==j) {
finallen=maxByteLen;
}else{
finallen=maxByteLen-i-1;
}
found=true;
break;
}
}
if(found) {
break;
}
i++;
}
datalen = new String(data,0,finallen).length();
return datalen;
}
public void checkMessageSize(CharSequence s,int maxTextLen,int oldLen) {
int mmssize = 0;
int MaxMmsSize = 0;
int textlen = s.length();
byte[] data = s.toString().getBytes();
int datasize = data.length;
SlideshowModel slideshow = mWorkingMessage.getSlideshow();
mTxtLength = textlen;
mTxtCompareRst = TextCompareResult.NOEXCEED_ANY_SIZE;
if(slideshow != null){
mmssize = slideshow.getTotalMsgSizeWithAllHead()-oldLen;
MaxMmsSize = MmsConfig.getPduMaxTotalSize();
if(mmssize>=MaxMmsSize) {
mTxtLength = 0;
mTxtCompareRst = TextCompareResult.EXCEED_ORGINAL_MAX_MMS_SIZE;
} else if(textlen > maxTextLen) {
s = s.subSequence(0, maxTextLen);
data = s.toString().getBytes();
datasize = data.length;
mTxtCompareRst = TextCompareResult.EXCEED_MAX_TEXT_SIZE;
if(mmssize+datasize > MaxMmsSize) {
datasize = MaxMmsSize - mmssize;
}
mTxtLength = CutByteToMaxLength(data,datasize);
} else if(mmssize+datasize > MaxMmsSize) {
mTxtCompareRst = TextCompareResult.EXCEED_MAX_MMS_SIZE;
datasize = MaxMmsSize - mmssize;
mTxtLength = CutByteToMaxLength(data,datasize);
} else {
mTxtCompareRst = TextCompareResult.NOEXCEED_ANY_SIZE;
mTxtLength = textlen;
}
} else {
if(textlen > maxTextLen) {
mTxtCompareRst = TextCompareResult.EXCEED_MAX_TEXT_SIZE;
mTxtLength = maxTextLen;
} else {
mTxtCompareRst = TextCompareResult.NOEXCEED_ANY_SIZE;
mTxtLength = textlen;
}
}
}
private class VcardProgressHandler extends Handler {
public VcardProgressHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
mVcardProgressDialog.dismiss();
}
}
private class myThread extends Thread {
private Uri uri;
private boolean append;
private boolean isAppendMedia = false;
public myThread(Uri uri, boolean append) {
this.uri = uri;
this.append = append;
}
public myThread(Uri uri, boolean append,boolean isAppendMedia) {
this.uri = uri;
this.append = append;
this.isAppendMedia = isAppendMedia;
}
@Override
public void run() {
addVcard(uri, append,isAppendMedia);
mEventHandler.handleMessage(null);
is_vcard_adding = false;
}
}
private class RotatePictureTask extends AsyncTask<Void, Void, Void> {
private Uri pictureUri = null;
@Override
protected Void doInBackground(Void... params) {
Log.d(TAG, "RotatePictureTask doInBackground Enter");
int position = getPositionOfadd();
Log.d(TAG, "RotatePictureTask position == " + position);
pictureUri = TempFileProvider.renameScrapFile(".jpg", Integer.toString(position),ComposeMessageActivity.this);
Log.d(TAG, "RotatePictureTask doInBackground pictureUri is"+pictureUri);
Log.d(TAG, "RotatePictureTask doInBackground Leave");
return null;
}
@Override
protected void onPostExecute(Void result) {
Log.d(TAG, "RotatePictureTask onPostExecute Enter");
super.onPostExecute(result);
if (pictureUri != null) {
Log.d(TAG, "RotatePictureTask onPostExecute pictureUri == " + pictureUri.toString());
addImage(pictureUri, false);
} else {
Toast.makeText(ComposeMessageActivity.this,
R.string.re_take_picture, Toast.LENGTH_SHORT).show();
}
Log.d(TAG, "RotatePictureTask onPostExecute Leave");
}
}
///////////////////////////////////below by lai////////////////////////////////////////////
/*
�˺�������:ÿ�������ƶ�ʱ������ǰ�Ķ��ŵ�Cursor�ҵ�
Ȼ������ʱ�ͷ�����һ��������ʱ�ͽ�����һ��
*/
private Cursor smsCursor;
private void SearchPhoneCursor(){
//Uri uri = Uri.parse("content://sms"); //��ȡ���еĶ���
Uri uri = Uri.parse("content://mms-sms/conversations"); //ֻ��ȡ�Ự����
/*liao*/
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplication());
String MmsPhoneNum = preferences.getString("phone_num", "");
String selection=" address <> '" + MmsPhoneNum + "' and address <> '+86" + MmsPhoneNum + "' ";
smsCursor = this.managedQuery(uri,new String[]{"thread_id","address"}, selection, null, "date DESC");
if(smsCursor != null){
if (smsCursor.moveToFirst()) {
do{
String phn=smsCursor.getString(1);
if(phn.equals(mPhoneNumForMms)){
break;
}
}while(smsCursor.moveToNext());
}
}
//smsCursor.close();
}
/*
androidϵͳ�е�ÿ��View�������������������TouchEvent����������صķ�����
1��public boolean dispatchTouchEvent(MotionEvent ev) ������������ַ�TouchEvent
2��public boolean onInterceptTouchEvent(MotionEvent ev) ���������������TouchEvent���������trueʱ�ͻ����onTouchEvent��
3��public boolean onTouchEvent(MotionEvent ev) ���������������TouchEvent�������ComposeMessageActivity.java��onTouchEvent���ᴥ����
�����Ҿij���dispatchTouchEventȥ����
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
/*liao*/
if(getIntent().getBooleanExtra("is_forbid_slide", false)){
return super.dispatchTouchEvent(ev);
}
/*liao*/
int action = ev.getAction();
float x = ev.getX();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
TOUNCH_ACTION_DOWN = true;
mStartMotionX = x;
break;
case MotionEvent.ACTION_MOVE:
TOUNCH_ACTION_MOVE = true;
break;
case MotionEvent.ACTION_UP:
SearchPhoneCursor();
mEndMotionX = x;
if(TOUNCH_ACTION_DOWN && TOUNCH_ACTION_MOVE){
if((mEndMotionX - mStartMotionX)>100){//����
if(smsCursor.moveToPrevious()){
startActivity(createIntent(this, smsCursor.getLong(0)));
overridePendingTransition(R.anim.in_from_left, R.anim.out_to_right);
smsCursor.close();//�ص�����
//finish();
}
}
else if((mEndMotionX - mStartMotionX)< -100){//����
if(smsCursor.moveToNext()){
startActivity(createIntent(this, smsCursor.getLong(0)));
overridePendingTransition(R.anim.in_from_right, R.anim.out_to_left);
smsCursor.close();//�ص�����
//finish();
}
}
}
TOUNCH_ACTION_MOVE = false;
TOUNCH_ACTION_DOWN = false;
break;
}
return super.dispatchTouchEvent(ev);
}
/* <activity android:name=".ui.ComposeMessageActivity"
android:theme="@/android:style/Theme.NoTitleBar"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop" > Ҫ�������android:launchMode="singleTop" ȥ��*/
private boolean TOUNCH_ACTION_DOWN = false;
private boolean TOUNCH_ACTION_MOVE = false;
private float mStartMotionX;
private float mEndMotionX;
///////////////////////////////////above by lai////////////////////////////////////////////
}