103

I want to take input, a URL or just a website name like, www.google.com from EditText in Android and on user click on the Button to submit or when the EditText looses the focus the URL should be validated, like it is in the format "www.anyURL.com"...

How can I do this? Is there any inbuilt functionality available in android?

ppreetikaa
  • 1,149
  • 2
  • 15
  • 22
Preetam
  • 5,528
  • 10
  • 32
  • 39

6 Answers6

316

Short answer

Use WEB_URL pattern in Patterns Class

 Patterns.WEB_URL.matcher(potentialUrl).matches()

It will return True if URL is valid and false if URL is invalid.

Long answer

As of Android API level 8 there is a WEB_URL pattern. Quoting the source, it "match[es] most part of RFC 3987". If you target a lower API level you could simply copy the pattern from the source and include it in your application. I assume you know how to use patterns and matchers, so I'm not going into more details here.

Also the class URLUtil provides some useful methods, e.g:

The descriptions of the methods are not very elaborate, therefore you are probably best of looking at the source and figuring out which one fits your purpose best.

As for when to trigger the validation check, there are multiple possibilities: you could use the EditText callback functions

or use a TextWatcher, which I think would be better.

DON'T USE URLUtil to validate the URL as below.

 URLUtil.isValidUrl(url)

because it gives strings like "http://" as valid URL which isn't true

Community
  • 1
  • 1
Dimi
  • 3,521
  • 1
  • 17
  • 10
  • 18
    If you look at the source for URLUtil, isValidUrl() and isHttpUrl() are basically the same as startsWith("http://") so be careful using these as you may not get the results you want. Using the WEB_URL pattern is much better suited to validating urls. – Dave Jun 18 '13 at 14:14
  • URLUtil.isValidUrl(downloadImageEditText.getText().toString()); – Prags Apr 23 '15 at 08:28
  • 1
    But as far as user input goes, the user won't try to type the 'http://' or 'https://' and would just write something like www.google.com or even google.com for an url, but these cases are not getting validated by the above solution, i guess the solution needs to include the tester's perception as well. – Sri Krishna Nov 30 '15 at 07:29
  • 2
    CAREFUL: Patterns.WEB_URL doesn't recognize "localhost" urls. – Artem Novikov Nov 27 '16 at 20:35
  • 2
    Patterns.WEB_URL doesn't recognise new domain names. e.g. https://abc.xyz/ (with https:// as prefix) (Web URL of Alphabet) – Chintan Shah May 04 '18 at 11:26
  • 1
    The problem with this solution is that it doesn't take into consideration poor url structure. Lets say you are constructing urls and you end up with this sort of situation, "google.com//home" (note the extra slash). You can pass in "google.com////////home", in fact, and it will still say it is a valid url. Which it is not. – portfoliobuilder Mar 02 '21 at 21:56
  • 1
    in my case the `potentialUrl` contains query parameters and `Patterns.WEB_URL.matcher(potentialUrl).matches()` returns false, what then ? – mihkov Jan 06 '22 at 20:40
22
/** 
* This is used to check the given URL is valid or not.
* @param url
* @return true if url is valid, false otherwise.
*/
private boolean isValidUrl(String url) {
    Pattern p = Patterns.WEB_URL;
    Matcher m = p.matcher(url.toLowerCase());
    return m.matches();
}
Codeversed
  • 9,287
  • 3
  • 43
  • 42
Shailendra Patil
  • 377
  • 2
  • 19
  • 4
    Web url must be in lowercase, otherwise Pattern returning false. just posting, so it may help somebody.. – praveenb Sep 25 '14 at 05:21
  • @praveenb above code snippet gives www.website is valid, without .com or .in it returns true. can you please tell how to make validation for this scenario? – Parth Patel Aug 13 '19 at 05:48
  • Why exactly must it be lowercase? Please don't just say "this is needed", also explain why it's needed! – Carsten Hagemann May 15 '20 at 09:26
10

In case, in your UnitTest, you got NullPointerException then use PatternsCompat instead of Patterns.

fun isFullPath(potentialUrl: String): Boolean {
    return PatternsCompat.WEB_URL.matcher(potentialUrl.toLowerCase(Locale.CANADA)).matches()
}

Also, I realized that this method returns true when I pass it Photo.jpg. My expectation is false. Therefore, I propose following method instead of the above.

fun isFullPath(potentialUrl: String): Boolean {
    try {
        URL(potentialUrl).toURI()
        return true
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return false
}
Hesam
  • 52,260
  • 74
  • 224
  • 365
2

URLUtil.isValidUrl will work since it exists since api level 1.

twig
  • 4,034
  • 5
  • 37
  • 47
  • 11
    This should not be the right answer if you [look at the code for it](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/URLUtil.java#URLUtil.isValidUrl%28java.lang.String%29) . It is just checking the initial scheme of URL, not that the entire URL is valid. This is probably one of the worst URL validations that I have seen – Mike Aug 25 '14 at 19:20
0

Use this regex on your website validation

String WebUrl = "^((ftp|http|https):\\/\\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\\.[a-zA-Z]+)+((\\/)[\\w#]+)*(\\/\\w+\\?[a-zA-Z0-9_]+=\\w+(&[a-zA-Z0-9_]+=\\w+)*)?$";


//TODO for website validation

private boolean isValidate() 
{

        String website = txtWebsite.getText().toString().trim();
        if (website.trim().length() > 0) {
            if (!website.matches(WebUrl)) {
                //validation msg
                return false;
            }
        }
        return true;

}
Nidhi Savaliya
  • 162
  • 2
  • 9
-4

Or you could just use good old Regex

Pattern urlRegex = Pattern.compile("((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(:[0-9]+)?|(?:ww‌​w.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?‌​(?:[\w]*))?)");

I am not saying that Patterns.WEB_URL is bad, it just it makes it easy to test what gets matched and what does not.

Community
  • 1
  • 1
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265