Кодировка URL в Android


336

Как вы кодируете URL в Android?

Я думал, что это было так:

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

Если я сделаю выше, http://вurlAsString замещается http%3A%2F%2Fв encodedURLа затем я получаю , java.net.MalformedURLExceptionкогда я использую URL.

Ответы:


631

Вы не кодируете весь URL-адрес, а только его части, полученные из «ненадежных источников».

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

Кроме того, вы можете использовать Strings.urlEncode (String str) из DroidParts , который не проверенные исключения.

Или использовать что-то вроде

String uri = Uri.parse("http://...")
                .buildUpon()
                .appendQueryParameter("key", "val")
                .build().toString();

1
Что если весь URL ненадежен? Должен ли я кодировать все, кроме протокола? Я вроде ожидал удобного способа сделать это.
hpique

5
Тогда это просто битый URL. Идея состоит в том, чтобы часть запроса не нарушала URL.
Янченко

5
@hgpc - взгляните на раздел 3 RFC3986 ( tools.ietf.org/html/rfc3986#section-3 ). Он говорит вам, как кодировать различные части URI. К сожалению, каждая часть URI (хост, путь, запрос и т. Д.) Имеет немного разные правила кодирования.
Д.Шоули

2
Это нормально, если вы просто имеете дело с определенной частью URL, и вы знаете, как создать или реконструировать URL. Для более общего подхода, который может обрабатывать любую строку URL, см. Мой ответ ниже.
Крейг Б

8
Почему я получаю предупреждение об устаревании, используя это? Используется Uri.encode(query);вместо
prasanthv

166

Я собираюсь добавить одно предложение здесь. Вы можете сделать это, чтобы избежать необходимости получать какие-либо внешние библиотеки.

Попробуйте это:

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

Вы можете видеть, что в этом конкретном URL мне нужно закодировать эти пробелы, чтобы я мог использовать его для запроса.

Это использует пару функций, доступных вам в классах Android. Во-первых, класс URL может разбить URL-адрес на соответствующие компоненты, поэтому вам не нужно выполнять поиск / замену строк. Во-вторых, этот подход использует преимущества класса URI для правильного экранирования компонентов, когда вы создаете URI через компоненты, а не из одной строки.

Прелесть этого подхода в том, что вы можете взять любую действительную строку URL-адреса и заставить ее работать, не требуя каких-либо специальных знаний о ней самостоятельно.


19
Это должен быть правильный ответ. это формальный и понятный способ сделать это
Асанка Сенавиратна

3
Также может быть хорошей идеей urldecode urlStr перед отправкой его в конструктор URL. URLDecoder.decode (urlStr)
Якоб Эрикссон

1
Спасибо за пост :) Но я столкнулся с проблемой. Если URL уже частично закодирован, он кодирует уже закодированные части. Что я должен делать? Например: dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/…% 20 закодирован в% 2520
берсерк

2
@berserk Если он уже закодирован, не кодируйте его. Вы не должны входить в состояние, когда оно частично закодировано, или вы не уверены, закодировано оно или нет.
маркиз Лорн

3
Этот метод не кодирует символы от ğ до% C4% 9F. Принимается один кодирует!
Александр Прокофьев

74

Для Android я бы использовал String android.net.Uri.encode (String s)

Кодирует символы в данной строке как «%» - экранированные октеты по схеме UTF-8. Оставляет буквы ("AZ", "az"), цифры ("0-9") и незарезервированные символы ("_- !. ~ '() *") без изменений. Кодирует все остальные символы.

Ex /

String urlEncoded = "http://stackoverflow.com/search?q=" + Uri.encode(query);

2
К сожалению, Uri.encode("a=1&b=1")производит, a%3D1%26b%3D1но ожидаетсяa=1&b=1
loentar

14
@loentar Это ожидаемый результат. Если пользователь вводит a=1&b=1как запрос, вы хотите запросить именно это.
Анубиан Нуб

Насколько это отличается от URLEncoder.encode (StringHere, "UTF-8")
stuckedoverflow

@stuckedoverflow Во-первых, Uri.encode (str) не выдает проверенное исключение в отличие от URLEncoder.encode (str, "UTF-8")
deekshith

50

Также вы можете использовать это

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

это самый простой метод


1
это не лучшее решение, но это определенно хорошее быстрое решение ... спасибо
Себастьян Брейт

4
Это самое быстрое исправление, когда весь URL ненадежен. Спасибо!
user1032613

Вы уверены, что% должен быть разрешен? Разве это не должно быть закодировано?
MediumOne

1
Как закодировать этот URL, чтобы можно было поделиться, и тогда пользователь сможет открыть ссылку и увидеть страницу: yazd20.com//News/2015/11/ استند-آب-كمدي-حسن-ريوندي-در-يزد. Html
Ахмад Эбрахими

3
try {
                    query = URLEncoder.encode(query, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

1

Вы можете использовать ниже методы

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

или

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

второй лучше первого


0

Найдите арабские символы и замените их кодировкой UTF-8. что-то вроде этого:

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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.