Codificação de URL no Android

335

Como você codifica um URL no Android?

Eu pensei que era assim:

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

Se eu fizer o acima, o http://in urlAsStringé substituído por http%3A%2F%2Fin encodedURLe recebo um java.net.MalformedURLExceptionquando uso o URL.

hpique
fonte

Respostas:

630

Você não codifica o URL inteiro, apenas partes dele provenientes de "fontes não confiáveis".

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

Como alternativa, você pode usar Strings.urlEncode (String str) de DroidParts que não lança exceções verificadas.

Ou use algo como

String uri = Uri.parse("http://...")
                .buildUpon()
                .appendQueryParameter("key", "val")
                .build().toString();
yanchenko
fonte
11
E se o URL inteiro não for confiável? Devo codificar tudo, exceto o protocolo? Eu meio que esperava um método de conveniência para fazer isso.
Hpique
5
Então é apenas um URL quebrado. A idéia é impedir que a parte da consulta quebre o URL.
Yanchenko
5
@hgpc - veja a seção 3 do RFC3986 ( tools.ietf.org/html/rfc3986#section-3 ). Ele mostra como codificar as várias partes de um URI. Infelizmente, cada parte do URI (host, caminho, consulta etc.) possui regras de codificação ligeiramente diferentes.
D.Shawley
2
Isso é bom, pois você está lidando apenas com uma parte específica de um URL e sabe como construir ou reconstruir o URL. Para uma abordagem mais geral que possa lidar com qualquer string de URL, veja minha resposta abaixo.
Craig B
8
Por que estou recebendo um aviso de descontinuação usando isso? Usado em Uri.encode(query);vez disso.
Prasanthv 06/04
166

Vou adicionar uma sugestão aqui. Você pode fazer isso, evitando a necessidade de obter bibliotecas externas.

Faça uma tentativa:

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

Você pode ver que, neste URL específico, preciso ter esses espaços codificados para que eu possa usá-lo para uma solicitação.

Isso tira proveito de alguns recursos disponíveis nas classes do Android. Primeiro, a classe de URL pode quebrar um URL em seus componentes adequados, para que você não precise executar nenhum trabalho de pesquisa / substituição de string. Em segundo lugar, essa abordagem aproveita o recurso da classe URI de componentes que escapam adequadamente quando você constrói um URI por meio de componentes, e não a partir de uma única sequência.

A vantagem dessa abordagem é que você pode pegar qualquer string de URL válida e fazê-la funcionar sem precisar de nenhum conhecimento especial dela.

Craig B
fonte
19
Essa deve ser a resposta correta. esta é a maneira formal e claro para fazer isso
Asanka Senavirathna
3
Também pode ser uma boa idéia urodecode urlStr antes de enviá-lo para o construtor de URL. URLDecoder.decode (urlStr)
Jakob Eriksson
11
Obrigado pelo post :) Mas estou enfrentando um problema. Se o URL já estiver parcialmente codificado, estará codificando as partes já codificadas. O que devo fazer? Por exemplo: dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/… O% 20 está codificado em% 2520
berserk
2
@berserk Se já estiver codificado, não o codifique. Você não deve entrar em um estado em que está parcialmente codificado ou não tem certeza se está ou não codificado.
Marquês de Lorne
3
Este método não codifica caracteres como 'a% C4% 9F. Aceito um codifica!
Alexander Prokofyev
74

Para android, eu usaria String android.net.Uri.encode (String s)

Codifica caracteres na sequência especificada como octetos com escape '%' usando o esquema UTF-8. Deixa letras ("AZ", "az"), números ("0-9") e caracteres não reservados ("_- !. ~ '() *") intactos. Codifica todos os outros caracteres.

Ex/

String urlEncoded = "http://stackoverflow.com/search?q=" + Uri.encode(query);
tanutapi
fonte
2
Infelizmente Uri.encode("a=1&b=1")produz, a%3D1%26b%3D1mas o esperadoa=1&b=1
loentar
14
@loentar Esse é o resultado esperado. Se o usuário digitar a=1&b=1como uma consulta, você deseja consultar exatamente isso.
Anubian Noob
Quão diferente isso com URLEncoder.encode (StringHere, "UTF-8")
stuckedoverflow
@stuckedoverflow Por um lado, o Uri.encode (str) não lança uma exceção verificada, diferentemente do URLEncoder.encode (str, "UTF-8")
deekshith 14/01
50

Também você pode usar isso

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

é o método mais simples

Jedo
fonte
11
esta não é a melhor solução, mas é definitivamente uma boa solução rápida ... obrigado #
Sebastian Breit 30/03
4
Essa é a correção mais rápida quando todo o URL não é confiável. Obrigado!
user1032613
Tem certeza de que a% deve ser permitida? Não deve ser codificado?
MediumOne 28/05
11
Como codificar esse URL para que seja possível compartilhar e, em seguida, o usuário possa abrir o link e ver a página: 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
fonte
1

você pode usar os métodos abaixo

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

ou

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

o segundo é melhor que o primeiro.

Elango
fonte
0

Encontre caracteres árabes e substitua-os por sua codificação UTF-8. algo assim:

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
fonte