352

How do you encode a URL in Android?

I thought it was like this:

final String encodedURL = URLEncoder.encode(urlAsString, "UTF-8");
URL url = new URL(encodedURL);

If I do the above, the http:// in urlAsString is replaced by http%3A%2F%2F in encodedURL and then I get a java.net.MalformedURLException when I use the URL.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
hpique
  • 112,774
  • 126
  • 328
  • 461

7 Answers7

660

You don't encode the entire URL, only parts of it that come from "unreliable sources".

  • Java:

    String query = URLEncoder.encode("apples oranges", "utf-8");
    String url = "http://stackoverflow.com/search?q=" + query;
    
  • Kotlin:

    val query: String = URLEncoder.encode("apples oranges", "utf-8")
    val url = "http://stackoverflow.com/search?q=$query"
    

Alternatively, you can use Strings.urlEncode(String str) of DroidParts that doesn't throw checked exceptions.

Or use something like

String uri = Uri.parse("http://...")
                .buildUpon()
                .appendQueryParameter("key", "val")
                .build().toString();
Khal91
  • 77
  • 8
yanchenko
  • 53,981
  • 33
  • 142
  • 163
  • 1
    What if the whole url is unreliable? Should I encode everything except the protocol? I kind of expected a convenience method to do this. – hpique Jul 20 '10 at 00:28
  • 5
    Then it's just a broken url. The idea is to prevent the query part from breaking the url. – yanchenko Jul 20 '10 at 00:37
  • 6
    @hgpc - take a look at section 3 of RFC3986 (http://tools.ietf.org/html/rfc3986#section-3). It tells you how to encode the various portions of a URI. Unfortunately each portion of the URI (host, path, query, etc.) has slightly different encoding rules. – D.Shawley Jul 20 '10 at 01:49
  • 2
    This is fine in you are just dealing with a specific part of a URL and you know how to construct or reconstruct the URL. For a more general approach which can handle any url string, see my answer below. – Craig B Jan 22 '12 at 17:08
  • @yanchenko What if the last path of my url is `apples ははは.pdf` so the space should be dealt with first, then encode it. So it's now `apples%20ははは.pdf` but then if you encode it after, it becomes `apples%2520%E3%81%AF%E3%81%AF%E3%81%AF.pdf` instead of `apples%20%E3%81%AF%E3%81%AF%E3%81%AF.pdf`. How do you handle spacing and encoding? – Compaq LE2202x Feb 04 '14 at 03:59
  • 9
    Why am I getting a deprecation warning using this? Used `Uri.encode(query);` instead. – prasanthv Apr 06 '14 at 16:13
  • @yanchenko I want to share link in social media (telegrm, viber,...) that contain utf-8, tried your way buy not good, what to do with this: http://yazd20.com//News/2015/11/استند-آب-كمدي-حسن-ريوندي-در-يزد.html – Ahmad Ebrahimi Nov 02 '15 at 21:17
  • Attention, the URL documentation states: "The URLEncoder and URLDecoder classes can also be used, but only for HTML form encoding, which is not the same as the encoding scheme defined in RFC2396." Therefore if you use this URL for example for HTTP calls, I believe the URI class should rather be used for encoding. – Miloš Černilovský Oct 05 '17 at 14:48
  • How do I set a custom caption? For example I read "Google" and it contains the url "https://www.google.it/" – Simone Oct 31 '18 at 16:04
172

I'm going to add one suggestion here. You can do this which avoids having to get any external libraries.

Give this a try:

String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();

You can see that in this particular URL, I need to have those spaces encoded so that I can use it for a request.

This takes advantage of a couple features available to you in Android classes. First, the URL class can break a url into its proper components so there is no need for you to do any string search/replace work. Secondly, this approach takes advantage of the URI class feature of properly escaping components when you construct a URI via components rather than from a single string.

The beauty of this approach is that you can take any valid url string and have it work without needing any special knowledge of it yourself.

Craig B
  • 4,558
  • 1
  • 22
  • 18
77

For android, I would use String android.net.Uri.encode(String s)

Encodes characters in the given string as '%'-escaped octets using the UTF-8 scheme. Leaves letters ("A-Z", "a-z"), numbers ("0-9"), and unreserved characters ("_-!.~'()*") intact. Encodes all other characters.

Ex/

String urlEncoded = "http://stackoverflow.com/search?q=" + Uri.encode(query);
tanutapi
  • 981
  • 8
  • 6
50

Also you can use this

private static final String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%";
String urlEncoded = Uri.encode(path, ALLOWED_URI_CHARS);

it's the most simple method

Jedo
  • 781
  • 6
  • 4
3
try {
                    query = URLEncoder.encode(query, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
Thiago
  • 9,554
  • 11
  • 68
  • 97
1

you can use below methods

public static String parseUrl(String surl) throws Exception
{
    URL u = new URL(surl);
    return new URI(u.getProtocol(), u.getAuthority(), u.getPath(), u.getQuery(), u.getRef()).toString();
}

or

public String parseURL(String url, Map<String, String> params)
{
    Builder builder = Uri.parse(url).buildUpon();
    for (String key : params.keySet())
    {
        builder.appendQueryParameter(key, params.get(key));
    }
    return builder.build().toString();
}

the second one is better than first.

Elango
  • 71
  • 2
0

Find Arabic chars and replace them with its UTF-8 encoding. some thing like this:

for (int i = 0; i < urlAsString.length(); i++) {
    if (urlAsString.charAt(i) > 255) {
        urlAsString = urlAsString.substring(0, i) + URLEncoder.encode(urlAsString.charAt(i)+"", "UTF-8") + urlAsString.substring(i+1);
    }
}
encodedURL = urlAsString;