web-dev-qa-db-fra.com

android: AutoLink pour les numéros de téléphone ne fonctionne pas toujours

J'ai un simple TextView avec le numéro de téléphone local 852112222 ou (8 5) 211 2222.

J'ai besoin que ce soit cliquable, alors naturellement j'ai utilisé Android:autoLink="all".
Mais pour une raison quelconque, je ne comprends pas que le même numéro de téléphone ne soit pas "lié" sur tous les appareils.

Sur l’appareil Genymotion, cela ne fonctionnait pas. Sur mon appareil OnePlus2 personnel, cela a fonctionné… .. Testé sur de nombreux appareils, sans succès.

Quel pourrait être le problème?
Préférences de compte d'utilisateur? Version Android? ORM? Autre chose?

12
Martynas Jurkus

Voici mon enquête.

J'ai créé un nouveau projet et ajouté Android:autoLink="all" à une vue de texte dans activity_main.xml. Grâce aux développeurs d'Android Studio, j'ai pu voir l'aperçu et j'ai trouvé quelque chose d'intéressant:

  • 12345 non lié
  • 123456 non lié
  • 1234567lié
  • 12345678lié
  • 123456789 non lié
  • 1234567890 ne ressemble pas
  • 12345678901lié
  • 123456789012 non lié

Le résultat est le même sur mon téléphone. Alors j'ai regardé dans le code source, cherché le mot clé autolink, puis j'ai trouvé ceci:

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
}

Donc, le mot clé est Linkify maintenant. Pour 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);
    }
}

Ensuite, quelque chose de grave est arrivé, le SDK n'a pas PhoneNumberUtil, plus précisément ces 3 classes ci-dessous:

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

Pour le moment, la première raison est apparue: Locale.getDefault().getCountry().
Je suis donc allé à la configuration, trouvé la langue, sélectionné le chinois. Le résultat est ci-dessous:

  • 12345lié
  • 123456lié
  • 1234567lié
  • 12345678lié
  • 123456789lié
  • 1234567890lié
  • 12345678901lié
  • 123456789012lié

Deuxièmement, pour le paquetage de com.Android.i18n.phonenumbers, j'ai trouvé ceci:
https://Android.googlesource.com/platform/external/libphonenumber/+/ics-factoryrom-2-release/Java/src/com/Android/i18n/phonenumbers
Si vous êtes intéressé, vérifiez le lien ci-dessus. Remarquez dans l'URL: ics-factoryrom-2-release. Je doute donc fortement que cela dépende de plate-forme.

Pour la solution, CleverAndroid a raison, prendre le contrôle intégral de LinkMovementMethod est une bonne option.

15
Chris Wong

Il suffit de faire ce qui suit

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());
}

et aussi retirer le 

Android:autoLink

depuis votre fichier xml

5
Harsh Agrawal

Pouvez-vous s'il vous plaît essayer ci-dessous le code. Définir l'attribut par programme.

Activité

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);

    }
}   

Vue

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/activity_main"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <TextView
        Android:id="@+id/textv1"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/textv2"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/textv3"
        Android:layout_width="match_parent"
        Android:layout_height="55dp" />

</LinearLayout>   

 enter image description here

Appareils de test

  1. Un plus un avec Android 7.1
  2. Genymotion. 4.1.1 - API 16
5
young

Je vous suggère juste pour ajouter le code pays et tout votre problème sera résolu,

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

Si nous ajoutons le code pays avant le numéro, aucune autre solution temporaire n’est alors nécessaire.

4
miPlodder

J'ai constaté de nombreuses incohérences lors de l'utilisation de la liaison automatique. Si vous travaillez du tout pour une version prod. Choisissez toujours SpannableStringBuilder avec LinkMovementMethod. Vous avez un bon contrôle sur la manière dont le texte doit être affiché.

L'extrait ci-dessous peut aider.

String phone = "your phone number";
String message = "Phone number is: ";

Spannable span = new SpannableString(String.format("%s\n%s",message, phone));
ForegroundColorSpan color = new ForegroundColorSpan(Res.color(R.color.blue));
ClickableSpan click = new ClickableSpan() {
    @Override
        public void onClick(View widget) {
            Navigator.dialer("your phone number");
        }
        public void updateDrawState(TextPaint ds) {// override updateDrawState
            ds.setUnderlineText(false); // set to false to remove underline
        }
    };

span.setSpan(color, message.length(), message.length() + phone.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
span.setSpan(click, message.length(), message.length() + phone.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

changesMessageLabel.setText(span);
changesMessageLabel.setMovementMethod(LinkMovementMethod.getInstance());
4
CleverAndroid

Harsh Agrawal answer a fonctionné pour moi dans les cas où le numéro de téléphone est de 11 chiffres ou plus avec 3 blocs. par exemple. 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);

J'ai dû appeler Linkify.addLinks après avoir configuré le texte pour que cela fonctionne.

Notez que Linkify.addLinks appelle déjà setMovementMethod dans la vue texte.

1
fluxeon

Pour les liaisons téléphoniques spécifiques, vous devez utiliser 

Android:autoLink="phone"

Pour plus, consultez: textview autolink

1
Ready Android