4

I want to make web links inside a textview clickable. I used this code

tv.setLinksClickable(true);
tv.setAutoLinkMask(Linkify.WEB_URLS);
Linkify.addLinks(tv, Linkify.WEB_URLS);

which does linkify the web site URLs but also seems to randomly link other text like z.xyz dzo.yzw and others.

How can I tell the linkify to only link URLs? To try and detect links starting with http:// or https:// beginnings I tried this pattern compiling

tv.setLinksClickable(true);
Pattern httpPattern = Pattern.compile("^(http|https)://");
Linkify.addLinks(tv, httpPattern,"");

but that did not work (no links were highlighted). Is that RegEx correct? What should the 3rd parameter to addLinks be?

Thanks for any tips to get this working.

Some1Else
  • 715
  • 11
  • 26

3 Answers3

5

Here'a s pattern that corresponds to RFC 3986 (URL standard):

public static final Pattern URL_PATTERN = Pattern.compile(
        "(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
                + "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
                + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

from: https://stackoverflow.com/a/5713866/2980992.

Community
  • 1
  • 1
konata
  • 168
  • 1
  • 4
  • 10
  • Saying it is an implementation of the RFC is a bit of a stretch here, isn't? The author said it started simpler and was getting more complex with tests. Still some people complained of some edge cases. – Dielson Sales Jan 09 '18 at 12:51
4

After much searching and trial and error, this is the solution. Do not use the default Linkiny.WEB_URLS. Use a custom regex pattern that looks for links. I used the following (et is an EditText).

et.setLinksClickable(true);
Pattern httpPattern = Pattern.compile("[a-z]+:\\/\\/[^ \\n]*");
Linkify.addLinks(et, httpPattern,"");

That will only linkify URLs and not other strings with 2 words separated by a full stop as Linkify.WEB_URLS can do.

If that regex is not good enough for your needs see the following link for heaps of tested alternatives that handle more complex cases https://mathiasbynens.be/demo/url-regex

Hope that helps someone else with the same issue.

Some1Else
  • 715
  • 11
  • 26
  • the given regex as well as default autolink works wrong for me on android 5 and 6. It includes next word to the link which goes after the actual link. – YTerle Apr 27 '18 at 10:36
0

You may go on this way:

String regex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
if (tv.getText().toString().matches(regex)) {
    tv.setLinksClickable(true);
    Linkify.addLinks(tv, Linkify.WEB_URLS);
}

More about URL regex: Regular expression to match URLs in Java

Community
  • 1
  • 1
walkmn
  • 2,322
  • 22
  • 29
  • That still highlights strings not starting with http. eg "z.xy" is highlighted as a URL. The regex does find an occurance of https, but the addLinks is still linkifying the entire textView. – Some1Else Nov 03 '15 at 22:39
  • For example, try "test https://www.test.com test https://www.blah.com test z.xy test" as the textView contents. Only the 2 URLs should be highlighted, but it also highlights z.xy as a URL too. Stackoverflow removed the https and http from that text, but the URLS should have them. – Some1Else Nov 03 '15 at 22:48
  • I dont understand, I tried this string -> "z.xy" and `tv.getText().toString().matches(regex)` returned `false`, and string -> "http://z.xy" returned `true`. Check your code, in my case the `if` works fine. – walkmn Nov 04 '15 at 07:32
  • 1
    OK, maybe my question was not clear enough. Try the full text string `This is a test http://test.com more text https://another.com text here z.xy and some more text` That will cause both the http and https links to be linkified but also highlight the z.xy as a link. I only want the http and https valid URLs highlighted and linkified. The regex check always returns true because there is https within the text, but that does not help highlighting only the valid links. Hope that clears things up. – Some1Else Nov 04 '15 at 18:07