android:自动链接的电话号码并不总是有效

时间:2016-11-24 14:14:04

标签: android linkify

我有一个简单的TextView,当地电话号码为852112222或(8 5)211 2222.

我需要它可以点击,所以我自然使用了android:autoLink="all" 但由于某种原因,我不明白同一个电话号码在所有设备上都没有“链接”。

在普通的Genymotion设备上,它不起作用。在我个人的OnePlus2设备上它工作。 在不同的设备上测试一堆 - 没有运气。

可能是什么问题?
用户帐户首选项? Android版本? ORM?还有别的吗?

12 个答案:

答案 0 :(得分:16)

这是我的调查。

我创建了一个新项目,并将android:autoLink="all"添加到activity_main.xml中的文字视图中。感谢Android Studio的开发人员,我可以看到预览,我发现了一些有趣的东西:

  • 12345未链接
  • 123456未链接
  • 1234567 已关联
  • 12345678 已关联
  • 123456789未链接
  • 1234567890没有喜欢
  • 12345678901 已关联
  • 123456789012未链接

我的手机上的结果是一样的。所以我查看了源代码,搜索了关键字 autolink ,然后我发现了这个:

private void setText(CharSequence text, BufferType type,
                     boolean notifyBefore, int oldlen) {

    ...
    // unconcerned code above

    if (mAutoLinkMask != 0) {
        Spannable s2;

        if (type == BufferType.EDITABLE || text instanceof Spannable) {
            s2 = (Spannable) text;
        } else {
            s2 = mSpannableFactory.newSpannable(text);
        }

        if (Linkify.addLinks(s2, mAutoLinkMask)) {
            text = s2;
            type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;

            /*
             * We must go ahead and set the text before changing the
             * movement method, because setMovementMethod() may call
             * setText() again to try to upgrade the buffer type.
             */
            mText = text;

            // Do not change the movement method for text that support text selection as it
            // would prevent an arbitrary cursor displacement.
            if (mLinksClickable && !textCanBeSelected()) {
                setMovementMethod(LinkMovementMethod.getInstance());
            }
        }
    }

    ...
    // unconcerned code above
}

所以关键字现在是Linkify。对于addLinks

public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
    ...

    if ((mask & PHONE_NUMBERS) != 0) {
        gatherTelLinks(links, text);
    }

    ...
}

private static final void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s) {
    PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
            Locale.getDefault().getCountry(), Leniency.POSSIBLE, Long.MAX_VALUE);
    for (PhoneNumberMatch match : matches) {
        LinkSpec spec = new LinkSpec();
        spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());
        spec.start = match.start();
        spec.end = match.end();
        links.add(spec);
    }
}

然后,发生了一些不好的事情,SDK没有PhoneNumberUtil,特别是以下3个类:

import com.android.i18n.phonenumbers.PhoneNumberMatch;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;

目前,第一个原因浮出水面:Locale.getDefault().getCountry() 所以我去设置,找到语言,选中文。结果如下:

  • 12345 已关联
  • 123456 已关联
  • 1234567 已关联
  • 12345678 已关联
  • 123456789 已关联
  • 1234567890 已关联
  • 12345678901 已关联
  • 123456789012 已关联

其次,对于com.android.i18n.phonenumbers的包裹,我发现了这一点:
https://android.googlesource.com/platform/external/libphonenumber/+/ics-factoryrom-2-release/java/src/com/android/i18n/phonenumbers
如果您有兴趣,请查看上面的链接。请注意网址:ics-factoryrom-2-release。所以我非常怀疑这是依赖于平台的

对于解决方案,CleverAndroid是正确的,完全控制LinkMovementMethod是一个不错的选择。

答案 1 :(得分:5)

请试试下面的代码。以编程方式设置属性。

<强>活动

NSError

查看

package custom.com.android_lab;

import android.app.Activity;
import android.os.Bundle;
import android.text.util.Linkify;
import android.widget.TextView;

/**
 * You can use Activity or AppCompatActivity
 */
public class MainActivity extends Activity {

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

        setContentView(R.layout.activity_main);

        // local phone number 852112222 or (8 5) 211 2222.

        // Tested OK!
        TextView textView1 = (TextView) findViewById(R.id.textv1);
        textView1.setAutoLinkMask(Linkify.PHONE_NUMBERS);
        textView1.setText("852112222");

        // Tested OK!
        TextView textView2 = (TextView) findViewById(R.id.textv2);
        textView2.setAutoLinkMask(Linkify.PHONE_NUMBERS);
        textView2.setText("(85) 211-2222");

        // Tested Failed!
        // Reason : Need to apply setAutoLinkMask prior to apply setText
        TextView textView3 = (TextView) findViewById(R.id.textv3);
        textView3.setText("852112222");
        textView2.setAutoLinkMask(Linkify.PHONE_NUMBERS);

    }
}   

enter image description here

测试设备

  1. Android 7.1的一加一
  2. Genymotion。 4.1.1 - API 16

答案 2 :(得分:5)

我建议您添加国家/地区代码,所有问题都将得到解决,

android:autoLink="phone"
android:text="+91-8000000000"

如果我们在数字之前添加国家/地区代码,则无需其他临时解决方案。

答案 3 :(得分:5)

只需执行以下操作

TextView userInput= (TextView) view.findViewById(R.id.textView);

if(userInput != null){
     Linkify.addLinks(userInput, Patterns.PHONE,"tel:",Linkify.sPhoneNumberMatchFilter,Linkify.sPhoneNumberTransformFilter);
     userInput.setMovementMethod(LinkMovementMethod.getInstance());
}

并删除

android:autoLink
来自xml文件的

答案 4 :(得分:4)

使用自动链接时,我看到了很多不一致的地方。如果你正在为一个prod版本工作。总是使用LinkMovementMethod去使用SpannableStringBuilder。您可以很好地控制文本的显示方式。

下面的代码段可能有所帮助。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <input id="list-input" />
  <button id="add">Add To List</button>
  <button id="delete">Remove From List</button>
</div>
<div class="container">
  <h1>Your List</h1>
  <div id="mylist">

  </div>
  <button id="clear">clear</button>
</div>

答案 5 :(得分:4)

Harsh Agrawal答案对我有用,如果电话号码是11位数字或3块以上。 例如123 456 78910

TextView textView = findViewById(R.id.text_view);
textView.setText("123 456 78910");
Linkify.addLinks(textView, Patterns.PHONE, "tel:", Linkify.sPhoneNumberMatchFilter,
            Linkify.sPhoneNumberTransformFilter);

设置了文本后,我不得不打电话给Linkify.addLinks

请注意,Linkify.addLinks已在文本视图上调用setMovementMethod

答案 6 :(得分:3)

为电话号码创建通用模式,然后添加Linkify掩码(科特琳,扩展功能):

fun TextView.makeLinkedable(){
    val pattern = Pattern.compile("""^[+]?[0-9]{10,13}""", Pattern.CASE_INSENSITIVE)
    LinkifyCompat.addLinks(this, Linkify.ALL)
    LinkifyCompat.addLinks(this, pattern, "tel://", null, null, null)
    setLinkTextColor(ContextCompat.getColor(context, R.color.blue))
}

应该适用于所有设备

答案 7 :(得分:0)

对于手机自动链接,您应该使用

android:autoLink="phone"

有关详情,请参阅:textview autolink

答案 8 :(得分:0)

autoLink =“电话”不接受某些号码

因此,您可以直接调用Phone Intent,将clickListener添加到TextView。

将电话声明为类属性:

private String phone = "1234567890";

在活动的onCreate()方法中:

//...
TextView  tvPhoneTelefone = (TextView) findViewById(R.id.tv_telefone);
tvPhone.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent callIntent = new Intent(Intent.ACTION_DIAL);
        callIntent.setData(Uri.parse("tel:" + phone ));
        startActivity(callIntent);
    }
});

这应该可以使用任何数字。

答案 9 :(得分:0)

Iliya Mashin's answer是最适合我的解决方案。

我为Java对其进行了修改,并至少指定了4个数字(因此它不会链接一些以3个数字“ xxxxx-xxx”结尾的邮政编码),因此,如果您不想使用此特定限制,只需删除结尾的“ {4,}”。

    LinkifyCompat.addLinks(textView, Linkify.ALL); // This will use the usual linkify for any other format
    Pattern pattern = Pattern.compile("([\\d|\\(][\\h|\\(\\d{3}\\)|\\.|\\-|\\d]{4,}\\d{4,})", Pattern.CASE_INSENSITIVE);
    LinkifyCompat.addLinks(textView, pattern, "tel://", null, null, null); // this adds the format for all kinds of phone number

如果只想链接数字,请删除第一行(带有“ Linkify.ALL”的那一行)。

答案 10 :(得分:0)

我使用linkify使电话号码可点击,并且对我有用

private val PHONE_NUMBER_VALIDATE = "^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\\s./0-9]*\$"

    val spannableString = SpannableString(mMarker.snippet)
    val pattern = Pattern.compile(PHONE_NUMBER_VALIDATE, Pattern.MULTILINE)
    LinkifyCompat.addLinks(spannableString, pattern, "tel://")
    textview.text = spannableString
    textview.movementMethod = LinkMovementMethod.getInstance()

确保您尚未在XML中添加android:autoLink="phone"

在这里,我尝试Pattern.MULTILINE来编译模式

Pattern.MULTILINE告诉Java接受锚^和$匹配 在每行的开头和结尾处(否则它们仅在 整个字符串的开始/结束。)

答案 11 :(得分:0)

我为 textview 创建了一个扩展函数,使电话号码在所有设备上都能正常工作:

import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.util.Patterns
import android.widget.TextView
import androidx.core.text.util.LinkifyCompat

fun TextView.compatMakeLinksClickable() {
    LinkifyCompat.addLinks(this, Linkify.ALL)
    // For some phone manufacturers (e.g. Moto G5 plus and some samsung devices)
    // Linkify.ALL does not work for phonenumbers
    // therefore we added the next line, to fix that:
    Linkify.addLinks(
        this, Patterns.PHONE, "tel:",
        Linkify.sPhoneNumberMatchFilter,
        Linkify.sPhoneNumberTransformFilter
    );
    this.movementMethod = LinkMovementMethod.getInstance()
}