• 解决:长按一条接收到的彩信,快捷菜单“选择性复制”功能错误


    【测试步骤】长按一条接收到的彩信,快捷菜单——“选择性复制”
    【测试结果】功能错误,未实现选择性复制,实际是播放彩信内容

    【预期结果】应该选择复制彩信内容

    通过分析代码我们定位到以下代码:

        private final class MsgListMenuClickListener implements MenuItem.OnMenuItemClickListener {
            private MessageItem mMsgItem;

            public MsgListMenuClickListener(MessageItem msgItem) {
                mMsgItem = msgItem;
            }

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                if (mMsgItem == null) {
                    return false;
                }

            ......

                    case MENU_SELECT_COPY_MESSAGE_TEXT:

                        AdapterView.AdapterContextMenuInfo info;
                        try {
                             info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
                        } catch (ClassCastException exception) {
                            Log.e(TAG, "Bad menuInfo.", exception);
                            return false;
                        }

                        final Cursor cursor = (Cursor) mMsgListAdapter.getItem(info.position);
                        if (mMsgItem.isSms()) {
                            showSmsMessageContent(cursor);
                        } else {
                            MessageUtils.viewMmsMessageAttachment(ComposeMessageActivity.this,
                                    ContentUris.withAppendedId(Mms.CONTENT_URI, mMsgItem.mMsgId), null,
                                    getAsyncDialog());
                        }

                        return true;

            ......

        }

    通过对以上代码我们发现,这里对彩信和短信分别进行了处理,在接着追踪代码时我们发现,如果信息为短信则现实短信的详细信息包括发件人,发件时间等,如果信息为彩信则直接进入彩信幻灯片播放界面,并播放幻灯片。与选项描述和原始业务逻辑相违背,因此作出一下修改。

    我们只提取信息的文本,如果信息为彩信,并且彩信只有附件,则屏蔽该选项(Select text to copy)。

    因此作出以下修改:

    修改ComposeMessageActivity文件中, OnCreateContextMenuListener子类中onCreateContextMenu()方法。

    这是修改前的源文件:

                ......

                // Forward is not available for undownloaded messages.
                if (msgItem.isDownloaded() && (msgItem.isSms() || msgItem.mIsForwardable)) {
                    menu.add(0, MENU_FORWARD_MESSAGE, 0, R.string.menu_forward)
                            .setOnMenuItemClickListener(l);
                }

                if (!msgItem.isMms() || msgItem.isDownloaded()) {
                    menu.add(0, MENU_SELECT_COPY_MESSAGE_TEXT, 0, R.string.select_copy_message_text)
                            .setOnMenuItemClickListener(l);
                }


                //only failed send message have resend function
                if (msgItem.isFailedMessage()) {
                        menu.add(0, MENU_RESEND, 0, R.string.menu_resend)
                                .setOnMenuItemClickListener(l);
                }

                ......

    下面是修改后的源代码:(将上述代码中蓝色加粗代码修改为下面红色加粗代码)



                ......

                // Forward is not available for undownloaded messages.
                if (msgItem.isDownloaded() && (msgItem.isSms() || msgItem.mIsForwardable)) {
                    menu.add(0, MENU_FORWARD_MESSAGE, 0, R.string.menu_forward)
                            .setOnMenuItemClickListener(l);
                }


                String selectText=null;
                selectText=msgItem.mBody;
                if( (!msgItem.isMms() || msgItem.isDownloaded())&&(selectText!=null)){
                    menu.add(0, MENU_SELECT_COPY_MESSAGE_TEXT, 0, R.string.select_copy_message_text)
                            .setOnMenuItemClickListener(l);
                }

                //only failed send message have resend function
                if (msgItem.isFailedMessage()) {
                        menu.add(0, MENU_RESEND, 0, R.string.menu_resend)
                                .setOnMenuItemClickListener(l);
                }

                ......


    添加SelectTextToCopyActivity文件,该类为对信息文本内容进行自由复制操作界面:

    package com.android.mms.ui;

    import java.util.ArrayList;

    import android.app.ActionBar;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.ProgressDialog;
    import android.content.ActivityNotFoundException;
    import android.content.AsyncQueryHandler;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.content.Intent;
    import android.database.Cursor;
    import android.database.sqlite.SqliteWrapper;
    import android.graphics.drawable.Drawable;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.provider.ContactsContract;
    import android.provider.ContactsContract.Contacts;
    import android.provider.Settings;
    import android.provider.Settings.SettingNotFoundException;
    import android.provider.Telephony.Mms;
    import android.provider.Telephony.Sms;
    import android.telephony.PhoneNumberUtils;
    import android.text.method.HideReturnsTransformationMethod;
    import android.text.style.URLSpan;
    import android.text.SpannableStringBuilder;
    import android.text.TextUtils;
    import android.view.GestureDetector;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.MotionEvent;
    import android.view.ScaleGestureDetector;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.Window;
    import android.util.Log;
    import android.util.TypedValue;
    import android.widget.ArrayAdapter;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.android.mms.data.Contact;
    import com.android.mms.LogTag;
    import com.android.mms.R;
    import com.android.mms.transaction.MessageSender;
    import com.android.mms.transaction.MessagingNotification;
    import com.android.mms.transaction.SmsMessageSender;
    import com.android.mms.ui.MessageUtils;
    import com.android.mms.ui.WwwContextMenuActivity;
    import com.android.mms.util.SmileyParser;
    import com.google.android.mms.MmsException;

    public class SelectTextToCopyActivity extends Activity {
        private static final String TAG = "SelectTextToCopyActivity";
        private String mMsgText;// Text of message

        private TextView mBodyTextView;
        private float mScaleFactor = 1;
        private  ScaleGestureDetector mScaleDetector;
        private  GestureDetector mGestureDetector;

        private static final int ZOOM_IN = 4;
        private static final int ZOOM_OUT = 5;
        private final int MAX_ZOOM_IN_SIZE = 60;
        private final int MAX_ZOOM_OUT_SIZE = 20;
        private final int THE_SIZE_OF_PER_ZOOM = 9;
        private float mTextSize = 27;
        private int mZoomMsg = -1;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
            setContentView(R.layout.activity_select_text_to_copy);
            getIntentData();
            initUi();
        }

        @Override
        public boolean onSearchRequested() {
            return false;
        }

        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case android.R.id.home:
                    finish();
                    break;
            }
            return true;
        }


        private void getIntentData() {
            Intent intent = getIntent();
            mMsgText = intent.getStringExtra("select");
        }

        private void initUi() {
            mBodyTextView = (TextView) findViewById(R.id.text_select);
            mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
            mBodyTextView.setTextIsSelectable(true);
            mBodyTextView.setText(formatMessage(mMsgText));
            mBodyTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onMailBoxMessageClick(SelectTextToCopyActivity.this);
                }
            });
            mScaleDetector = new ScaleGestureDetector(this, new MyScaleListener());
            mGestureDetector = new GestureDetector(this,
                    new GestureDetector.SimpleOnGestureListener(){ });
            mGestureDetector.setOnDoubleTapListener(null);
            ActionBar actionBar = getActionBar();
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        public void onMailBoxMessageClick(final Context context) {
            // Check for links. If none, do nothing; if 1, open it; if >1, ask user
            // to pick one
            final URLSpan[] spans = mBodyTextView.getUrls();
            if (spans.length == 1) {
                String url = spans[0].getURL();
                if (MessageUtils.isWebUrl(url)) {
                    Uri uri = Uri.parse(url);
                    Intent intent = new Intent(context, WwwContextMenuActivity.class);
                    intent.setData(uri);
                    context.startActivity(intent);
                } else {
                    final String telPrefix = "tel:";
                    if (url.startsWith(telPrefix)) {
                        url = url.substring(telPrefix.length());
                    }
                    if (PhoneNumberUtils.isWellFormedSmsAddress(url)) {
                        MessageUtils.showNumberOptions(this, url);
                    } else {
                        spans[0].onClick(mBodyTextView);
                    }
                }
            } else if (spans.length > 1) {
                ArrayAdapter<URLSpan> adapter = new ArrayAdapter<URLSpan>(context,
                        android.R.layout.select_dialog_item, spans) {

                    @Override
                    public View getView(int position, View convertView, ViewGroup parent) {
                        View v = super.getView(position, convertView, parent);
                        try {
                            URLSpan span = getItem(position);
                            String url = span.getURL();
                            Uri uri = Uri.parse(url);
                            TextView tv = (TextView) v;
                            Drawable d = context.getPackageManager().getActivityIcon(
                                    new Intent(Intent.ACTION_VIEW, uri));
                            if (d != null) {
                                d.setBounds(0, 0, d.getIntrinsicHeight(),
                                        d.getIntrinsicHeight());
                                tv.setCompoundDrawablePadding(10);
                                tv.setCompoundDrawables(d, null, null, null);
                            }
                            // If prefix string is "mailto" then translate
                            // it.
                            final String mailPrefix = "mailto:";
                            String tmpUrl = null;
                            if (url != null) {
                                if (url.startsWith(mailPrefix)) {
                                    url = context.getResources().getString(R.string.mail_to) +
                                            url.substring(mailPrefix.length());
                                }
                                tmpUrl = url.replaceAll("tel:", "");
                            }
                            tv.setText(tmpUrl);
                        } catch (android.content.pm.PackageManager.NameNotFoundException ex) {
                            // it's ok if we're unable to set the drawable
                            // for this view - the user
                            // can still use it
                        }
                        return v;
                    }
                };

                AlertDialog.Builder b = new AlertDialog.Builder(context);

                DialogInterface.OnClickListener click = new DialogInterface.OnClickListener() {
                    @Override
                    public final void onClick(DialogInterface dialog, int which) {
                        if (which >= 0) {
                            String url = spans[which].getURL();
                            if (MessageUtils.isWebUrl(url)) {
                                Uri uri = Uri.parse(url);
                                Intent intent = new Intent(SelectTextToCopyActivity.this,
                                        WwwContextMenuActivity.class);
                                intent.setData(uri);
                                context.startActivity(intent);
                            } else {
                                final String telPrefix = "tel:";
                                if (url.startsWith(telPrefix)) {
                                    url = url.substring(telPrefix.length());
                                }
                                if (PhoneNumberUtils.isWellFormedSmsAddress(url)) {
                                    MessageUtils.showNumberOptions(context, url);
                                } else {
                                    spans[which].onClick(mBodyTextView);
                                }
                            }
                        }
                        dialog.dismiss();
                    }
                };

                b.setTitle(R.string.select_link_title);
                b.setCancelable(true);
                b.setAdapter(adapter, click);

                b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public final void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });

                b.show();
            }
        }

        private Handler mUiHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case ZOOM_IN:
                     zoomIn();
                     mBodyTextView.invalidate();
                     break;
                case ZOOM_OUT:
                     zoomOut();
                     mBodyTextView.invalidate();
                     break;
                default:
                    break;
                }
            }
        };

        private void zoomIn() {
            mTextSize = mTextSize + THE_SIZE_OF_PER_ZOOM <= MAX_ZOOM_IN_SIZE ?
                    mTextSize + THE_SIZE_OF_PER_ZOOM : MAX_ZOOM_IN_SIZE;
            if (mTextSize >= MAX_ZOOM_IN_SIZE) {
                mTextSize = MAX_ZOOM_IN_SIZE;
            }
            mBodyTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,mTextSize);
        }

        private void zoomOut() {
            mTextSize = mTextSize - THE_SIZE_OF_PER_ZOOM < MAX_ZOOM_OUT_SIZE ?
                    MAX_ZOOM_OUT_SIZE : mTextSize - THE_SIZE_OF_PER_ZOOM;
            if (mTextSize <= MAX_ZOOM_OUT_SIZE) {
               mTextSize = MAX_ZOOM_OUT_SIZE;
            }
            mBodyTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,mTextSize);
        }

        private class MyScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                float scale = detector.getScaleFactor();
                if (scale < 0.999999 || scale > 1.00001) {
                    mScaleFactor = scale;
                }
                return true;
            }

            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                float scale = detector.getScaleFactor();
                if (mScaleFactor > 1.0) {
                    mZoomMsg = ZOOM_IN;
                } else if (mScaleFactor < 1.0) {
                    mZoomMsg = ZOOM_OUT;
                }
            }
        }

        public boolean onInterceptTouchEvent(MotionEvent ev) {
            mScaleDetector.onTouchEvent(ev);
            final int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mGestureDetector.onTouchEvent(ev);
                    return false;

                case MotionEvent.ACTION_MOVE:
                   mGestureDetector.onTouchEvent(ev);
                   return false;

                case MotionEvent.ACTION_UP:
                    mGestureDetector.onTouchEvent(ev);
                    Message msg = Message.obtain();
                    msg.what = mZoomMsg;
                    mUiHandler.sendMessage(msg);
                    mZoomMsg = -1;
                    return false;
            }
            return true;
        }

        public boolean onTouchEvent(MotionEvent ev) {
            mScaleDetector.onTouchEvent(ev);
            final int action = ev.getAction();

            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mGestureDetector.onTouchEvent(ev);
                   return true;

                case MotionEvent.ACTION_MOVE:
                   mGestureDetector.onTouchEvent(ev);
                   return true;

                case MotionEvent.ACTION_UP:
                    mGestureDetector.onTouchEvent(ev);
                    Message msg = Message.obtain();
                    msg.what = mZoomMsg;
                    mUiHandler.sendMessage(msg);
                    mZoomMsg = -1;
                    return true;

                case MotionEvent.ACTION_CANCEL:
                    mGestureDetector.onTouchEvent(ev);
                    return true;

                default:
                    if (mGestureDetector.onTouchEvent(ev)) {
                        return true;
                    }

               return true;
            }
        }

        private CharSequence formatMessage(String body) {
            SpannableStringBuilder buf = new SpannableStringBuilder();
            if (!TextUtils.isEmpty(body)) {
                SmileyParser parser = SmileyParser.getInstance();
                buf.append(parser.addSmileySpans(body));
            }
            return buf;
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            mUiHandler.removeCallbacksAndMessages(null);
        }
    }


    添加activity_select_text_to_copy.xml文件,为相对应布局文件:

    <?xml version="1.0" encoding="utf-8"?>

    <!-- AddBy:yabin.huang BugID:SWBUG00030439 Date:20140626 -->

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/outlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:gravity="center_horizontal"
        android:isScrollContainer="true"
        android:orientation="vertical" >

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:minHeight="50dip"
                    android:orientation="vertical" >

                    <TextView
                        android:id="@+id/text_select"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:autoLink="all"
                        android:linksClickable="false"
                        android:padding="20dp"
                        android:textColor="#000000"
                        android:textSize="18dip" />
                </LinearLayout>

    </LinearLayout>

    并在清单文件中对Activity进行注册:

            <activity android:name=".ui.SelectTextToCopyActivity"
                android:label="@string/select_copy_message_text"
                android:theme="@style/MmsHoloTheme"
                android:configChanges="orientation|screenSize|keyboardHidden"
                android:launchMode="singleTop" >
            </activity>


    OK!问题得到解决。

  • 相关阅读:
    896. 单调数列
    819. 最常见的单词
    collections.Counter()
    257. 二叉树的所有路径
    万里长征,始于足下——菜鸟程序员的学习总结(三)
    Ogre启动过程&原理
    Ogre导入模型
    四元数
    Ogre3D嵌入Qt框架
    如何搭建本地SVN服务
  • 原文地址:https://www.cnblogs.com/bill-technology/p/4130865.html
Copyright © 2020-2023  润新知