我们可以认为这是一个很人性的格式化操作,在ComposeMessageActivity中系统在调用initRecipientsEditor()方法对联系人进行初始化的时候调用了 PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(this, mRecipientsEditor);我们通过对代码进行追踪发现,最终调用了Framework中PhoneNumberFormattingTextWatcher类对电话号码进行格式化处理,并在处理后在PhoneNumberFormatter中使用异步类控件的值进行处理,这里贴处该类的代码进行分析。

package android.telephony;



import com.android.i18n.phonenumbers.AsYouTypeFormatter;

import com.android.i18n.phonenumbers.PhoneNumberUtil;



import android.telephony.PhoneNumberUtils;

import android.text.Editable;

import android.text.Selection;

import android.text.TextWatcher;



import java.util.Locale;



/**

 * Watches a {@link android.widget.TextView} and if a phone number is entered

 * will format it.

 * <p>

 * Stop formatting when the user

 * <ul>

 * <li>Inputs non-dialable characters</li>

 * <li>Removes the separator in the middle of string.</li>

 * </ul>

 * <p>

 * The formatting will be restarted once the text is cleared.

 */

public class PhoneNumberFormattingTextWatcher implements TextWatcher {



    /**

     * Indicates the change was caused by ourselves.

     */

    private boolean mSelfChange = false;



    /**

     * Indicates the formatting has been stopped.

     */

    private boolean mStopFormatting;



    private AsYouTypeFormatter mFormatter;



    /**

     * The formatting is based on the current system locale and future locale changes

     * may not take effect on this instance.

     */

    public PhoneNumberFormattingTextWatcher() {

        this(Locale.getDefault().getCountry());

    }



    /**

     * The formatting is based on the given <code>countryCode</code>.

     *

     * @param countryCode the ISO 3166-1 two-letter country code that indicates the country/region

     * where the phone number is being entered.

     *

     * @hide

     */

    public PhoneNumberFormattingTextWatcher(String countryCode) {

        if (countryCode == null) throw new IllegalArgumentException();

        mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);

    }



    @Override

    public void beforeTextChanged(CharSequence s, int start, int count,

            int after) {

        if (mSelfChange || mStopFormatting) {

            return;

        }

        // If the user manually deleted any non-dialable characters, stop formatting

        if (count > 0 && hasSeparator(s, start, count)) {

            stopFormatting();

        }

    }



    @Override

    public void onTextChanged(CharSequence s, int start, int before, int count) {

        if (mSelfChange || mStopFormatting) {

            return;

        }

        // If the user inserted any non-dialable characters, stop formatting

        if (count > 0 && hasSeparator(s, start, count)) {

            stopFormatting();

        }

    }



    @Override

    public synchronized void afterTextChanged(Editable s) {

        if (mStopFormatting) {

            // Restart the formatting when all texts were clear.

            mStopFormatting = !(s.length() == 0);

            return;

        }

        if (mSelfChange) {

            // Ignore the change caused by s.replace().

            return;

        }

        String formatted = reformat(s, Selection.getSelectionEnd(s));

        if (formatted != null) {

            int rememberedPos = mFormatter.getRememberedPosition();

            mSelfChange = true;

            s.replace(0, s.length(), formatted, 0, formatted.length());

            // The text could be changed by other TextWatcher after we changed it. If we found the

            // text is not the one we were expecting, just give up calling setSelection().

            if (formatted.equals(s.toString())) {

                Selection.setSelection(s, rememberedPos);

            }

            mSelfChange = false;

        }

    }



    /**

     * Generate the formatted number by ignoring all non-dialable chars and stick the cursor to the

     * nearest dialable char to the left. For instance, if the number is  (650) 123-45678 and '4' is

     * removed then the cursor should be behind '3' instead of '-'.

     */

    private String reformat(CharSequence s, int cursor) {

        // The index of char to the leftward of the cursor.

        int curIndex = cursor - 1;

        String formatted = null;

        mFormatter.clear();

        char lastNonSeparator = 0;

        boolean hasCursor = false;

        int len = s.length();

        for (int i = 0; i < len; i++) {

            char c = s.charAt(i);

            if (PhoneNumberUtils.isNonSeparator(c)) {

                if (lastNonSeparator != 0) {

                    formatted = getFormattedNumber(lastNonSeparator, hasCursor);

                    hasCursor = false;

                }

                lastNonSeparator = c;

            }

            if (i == curIndex) {

                hasCursor = true;

            }

        }

        if (lastNonSeparator != 0) {

            formatted = getFormattedNumber(lastNonSeparator, hasCursor);

        }

        return formatted;

    }



    private String getFormattedNumber(char lastNonSeparator, boolean hasCursor) {

        return hasCursor ? mFormatter.inputDigitAndRememberPosition(lastNonSeparator)

                : mFormatter.inputDigit(lastNonSeparator);

    }



    private void stopFormatting() {

        mStopFormatting = true;

        mFormatter.clear();

    }



    private boolean hasSeparator(final CharSequence s, final int start, final int count) {

        for (int i = start; i < start + count; i++) {

            char c = s.charAt(i);

            if (!PhoneNumberUtils.isNonSeparator(c)) {

                return true;

            }

        }

        return false;

    }

}

通过查看PhoneNumberFormattingTextWatcher代码我们发现,该类继承至TextWatcher,则实现了对RecipientEditor的值的变化进行了监听,最后调用PhoneNumberUtils进行处理。

分析:新建短信,当我们接受人RecipientsEditor中输入+86的时候,系统会自动在+86后加入空格的更多相关文章

  1. 将安卓手机短信导入到iPhone6 plus中

    不越狱的情况下短信不能直接同步到iphone手机,视频.图片.联系人可以直接使用itools的手机搬家功能超方便从android到iphone中.短信得变通的处理才能导入. 工具: 安卓手机iPhon ...

  2. Flask实战第43天:把图片验证码和短信验证码保存到memcached中

    前面我们已经获取到图片验证码和短信验证码,但是我们还没有把它们保存起来.同样的,我们和之前的邮箱验证码一样,保存到memcached中 编辑commom.vews.py .. from utils i ...

  3. android 在新建短信时,加入名称为","(英文逗号)的联系人时,应用崩溃的修改

    请修改文件 /alps/frameworks/ex/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java private sta ...

  4. Android系统自带APP分析——短信app

    Android操作系统本身就是一个巨大的开源软件仓库,熟悉它既可以了解到Android系统的设计框架,也可以获得高效的应用程序编写方式.本文所分析的源码来自于Google官方的AOSP源码4.0.1_ ...

  5. Android 短信模块分析(四) MMS之短信的发送与接收

     MMS之短信的发送与接收分析: 一.信息发送: com.android.mms.data.WorkingMessage.java 类 send()函数: public void send() { . ...

  6. PhpSms 稳定可靠的php短信发送库

    可能是目前最聪明.优雅的PHP短信发送库了.从此不再为各种原因造成的个别短信发送失败而烦忧! phpsms的任务均衡调度功能由toplan/task-balancer提供. GitHub地址:http ...

  7. C#利用Web Service实现短信发送(转)

    通过编程方式实现短信息的发送对很多人来说是一件比较烦杂的事情,目前一般的解决方法是通过计算机和手机的连线,通过可对手机编程的语言编写相关的手机短信息程序来实现,而这种方法对于一般人来说是很难达到的,因 ...

  8. android: 接收和发送短信

    8.2    接收和发送短信 收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这 项功能,而 Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.每个 A ...

  9. [android] 短信发送器

    /*****************2016年4月23日 更新********************************/ 知乎:什么是 7 位元的字符? 英文字符难道不是 8 bit 是一个字 ...

随机推荐

  1. mui --- 怎么获取百度地图定位功能

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 【Python】【元编程】【一】动态属性和特性

    #19.1 使用动态属性转换数据"""#栗子19-2 osconfeed.py:下载 osconfeed.jsonfrom urllib.request import u ...

  3. 51nod 1232 完美数 数位dp

    1232 完美数 题目来源: 胡仁东 基准时间限制:2 秒 空间限制:131072 KB  如果一个数能够被组成它的各个非0数字整除,则称它是完美数.例如:1-9都是完美数,10,11,12,101都 ...

  4. pandas demo 示例

    #构造 import pandas as pd import pickle import numpy as np dates=pd.date_range() df = pd.DataFrame(np. ...

  5. MarkChanges: Jmeter

    1. 20180627 调整启动的内存set HEAP=-Xms1024m -Xmx1024m2. 20180627 调整输出格式为xml #jmeter.save.saveservice.outpu ...

  6. Java 面向对象之继承和重写OverWrite,重写和重载的区别,抽象类

    01继承的概述 A:继承的概念 a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系 b:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作 ...

  7. Codeforces 862C - Mahmoud and Ehab and the xor

    862C - Mahmoud and Ehab and the xor 思路:找两对异或后等于(1<<17-1)的数(相当于加起来等于1<<17-1),两个再异或一下就变成0了 ...

  8. angular5 ng-bootstrap和ngx-bootstrap区别

    https://angular.cn/resources ngx-bootstrap 安装: npm install ngx-bootstrap --save 再引入css <link href ...

  9. 拓扑排序 Topological Sort

    2018-05-02 16:26:07 在计算机科学领域,有向图的拓扑排序或拓扑排序是其顶点的线性排序,使得对于从顶点u到顶点v的每个有向边uv,u在排序中都在v前.例如,图形的顶点可以表示要执行的任 ...

  10. Confluence 6 导入 Active Directory 服务器证书 - UNIX

    为了让你的应用服务器能够信任你的目录服务器.你目录服务器上导出的证书需要导入到你应用服务器的 Java 运行环境中.JDK 存储了信任的证书,这个存储信任证书的文件称为一个 keystore.默认的 ...