Kodowanie URL w Androidzie

336

Jak kodujesz adres URL w Androidzie?

Myślałem, że to tak:

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

Jeśli zrobię powyższe, znak http://in urlAsStringzostanie zastąpiony przez http%3A%2F%2Fin, encodedURLa następnie dostanę a, java.net.MalformedURLExceptiongdy użyję adresu URL.

hpique
źródło

Odpowiedzi:

630

Nie kodujesz całego adresu URL, tylko jego części, które pochodzą z „niewiarygodnych źródeł”.

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

Alternatywnie możesz użyć Strings.urlEncode (String str) z DroidParts, który nie zgłasza sprawdzonych wyjątków.

Lub użyj czegoś takiego

String uri = Uri.parse("http://...")
                .buildUpon()
                .appendQueryParameter("key", "val")
                .build().toString();
Janchenko
źródło
1
Co jeśli cały adres URL jest zawodny? Czy powinienem kodować wszystko oprócz protokołu? Oczekiwałem, że będzie to wygodna metoda.
hpique
5
To tylko zepsuty adres URL. Chodzi o to, aby zapobiec uszkodzeniu adresu URL przez część zapytania.
yanchenko
5
@hgpc - spójrz na sekcję 3 RFC3986 ( tools.ietf.org/html/rfc3986#section-3 ). Mówi ci, jak zakodować różne części identyfikatora URI. Niestety każda część identyfikatora URI (host, ścieżka, zapytanie itp.) Ma nieco inne reguły kodowania.
D.Shawley,
2
To dobrze, ponieważ masz do czynienia z określoną częścią adresu URL i wiesz, jak skonstruować lub zrekonstruować adres URL. Aby uzyskać bardziej ogólne podejście, które może obsłużyć dowolny ciąg adresu URL, zobacz moją odpowiedź poniżej.
Craig B
8
Dlaczego otrzymuję ostrzeżenie o wycofaniu się z tego powodu? Używany Uri.encode(query);zamiast.
prasanthv
166

Dodam tutaj jedną sugestię. Możesz to zrobić, co pozwala uniknąć pobierania zewnętrznych bibliotek.

Wypróbuj to:

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

Widać, że w tym konkretnym adresie URL muszę zakodować te spacje, aby móc użyć go do żądania.

Wykorzystuje to kilka funkcji dostępnych w klasach Androida. Po pierwsze, klasa URL może rozbić adres URL na odpowiednie komponenty, więc nie trzeba wykonywać żadnych operacji wyszukiwania / zamiany łańcucha. Po drugie, w tym podejściu wykorzystuje się właściwość klasy URI polegającą na prawidłowym ucieczce komponentów podczas tworzenia identyfikatora URI za pomocą komponentów, a nie pojedynczego łańcucha.

Piękno tego podejścia polega na tym, że możesz wziąć dowolny prawidłowy ciąg adresu URL i sprawić, aby działał bez potrzeby specjalnej wiedzy na jego temat.

Craig B.
źródło
19
To powinna być poprawna odpowiedź. jest to formalny i jasny sposób na zrobienie tego
Asanka Senavirathna
3
Dobrym pomysłem może być także urldSode przed wysłaniem go do konstruktora URL. URLDecoder.decode (urlStr)
Jakob Eriksson
1
Dzięki za post :) Ale mam problem. Jeśli adres URL jest już częściowo zakodowany, koduje już zakodowane części. Co powinienem zrobić? Na przykład: dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/...% 20 jest zakodowany na% 2520
szaleństwo
2
@berserk Jeśli jest już zakodowany, nie koduj go. Nie powinieneś wchodzić w stan, w którym jest on częściowo zakodowany lub nie masz pewności, czy jest zakodowany, czy nie.
Markiz Lorne
3
Ta metoda nie koduje znaków takich jak ğ do% C4% 9F. Zaakceptowano jeden kod!
Alexander Prokofyev
74

Dla Androida użyłbym String android.net.Uri.encode (String s)

Koduje znaki w podanym łańcuchu jako „%” - uciekł oktety przy użyciu schematu UTF-8. Pozostawia nienaruszone litery („AZ”, „az”), cyfry („0-9”) i niezarezerwowane znaki („_- !. ~ '() *”). Koduje wszystkie pozostałe znaki.

Dawny/

String urlEncoded = "http://stackoverflow.com/search?q=" + Uri.encode(query);
tanutapi
źródło
2
Niestety Uri.encode("a=1&b=1")produkuje, a%3D1%26b%3D1ale oczekuje sięa=1&b=1
Loentar
14
@loentar To oczekiwany wynik. Jeśli użytkownik wpisze a=1&b=1jako zapytanie, chcesz zapytać dokładnie o to.
Anubian Noob,
Jak inaczej to wygląda w przypadku URLEncoder.encode (StringHere, „UTF-8”)
zablokowany przepływ
@stuckedoverflow Po pierwsze, Uri.encode (str) nie zgłasza sprawdzonego wyjątku w przeciwieństwie do URLEncoder.encode (str, „UTF-8”)
Deekshith
50

Możesz także tego użyć

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

to najprostsza metoda

Jedo
źródło
1
nie jest to najlepsze rozwiązanie, ale zdecydowanie jest to fajna szybka naprawa ... dzięki
Sebastian Breit
4
Jest to najszybsza poprawka, gdy cały adres URL jest zawodny. Dzięki!
user1032613,
Czy jesteś pewien, że% powinno być dozwolone? Czy nie należy go kodować?
MediumOne
1
Jak zakodować ten adres URL, aby można go było udostępnić, a następnie użytkownik będzie mógł otworzyć link i wyświetlić stronę: yazd20.com//News/2015/11/ استند-آب-كمدي-حسن-ريوندي-در-يزد. Html
Ahmad Ebrahimi
3
try {
                    query = URLEncoder.encode(query, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
Joolah
źródło
1

możesz użyć poniższych metod

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

lub

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

drugi jest lepszy niż pierwszy.

Elango
źródło
0

Znajdź arabskie znaki i zamień je na kodowanie UTF-8. coś takiego:

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;
Ali Jafari
źródło