Utilizzare il generatore URI in Android o creare un URL con variabili


202

Sto sviluppando un'app Android. Devo creare un URI per la mia app per effettuare una richiesta API. A meno che non ci sia un altro modo per inserire una variabile in un URI, questo è il modo più semplice che ho trovato. Ho scoperto che devi usare Uri.Builder, ma non sono sicuro di come. Il mio URL è:

http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=[redacted]&mapid=value 

Il mio schema è http, autorità è lapi.transitchicago.com, percorso è /api/1.0, segmento (i) percorso (i) è ttarrivals.aspxe stringa di query è key=[redacted]&mapid=value.

Il mio codice è sotto:

Intent intent = getIntent();
String value = intent.getExtras().getString("value");
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
    .authority("www.lapi.transitchicago.com")
    .appendPath("api")
    .appendPath("1.0")
    .appendPath("ttarrivals.aspx")
    .appendQueryParameter("key", "[redacted]")
    .appendQueryParameter("mapid", value);

Capisco che posso fare URI.add, ma come posso integrarlo nel Uri.Builder? Dovrei aggiungere tutto come URI.add(scheme), URI.add(authority)e così via? O non è questo il modo di farlo? Inoltre, esiste un altro modo più semplice per aggiungere una variabile a un URI / URL?

Risposte:


426

Diciamo che voglio creare il seguente URL:

https://www.myawesomesite.com/turtles/types?type=1&sort=relevance#section-name

Per costruire questo con il Uri.Builderfarei quanto segue.

Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
    .authority("www.myawesomesite.com")
    .appendPath("turtles")
    .appendPath("types")
    .appendQueryParameter("type", "1")
    .appendQueryParameter("sort", "relevance")
    .fragment("section-name");
String myUrl = builder.build().toString();

1
Con il mio segmento di percorso, sarebbe un percorso? O sarebbe una domanda?
hichris123,

Se è un percorso, lo sarebbe appendPath()per il metodo. Se si tratta di una stringa di query (dopo il?) Quindi utilizzare appendQueryParameter(). Dai un'occhiata all'URL che ho nell'esempio e cosa sto facendo con ogni segmento. Ho anche aggiunto toString()alla build()chiamata per recuperare il tipo corretto.
David,

1
È prima del punto interrogativo, ma non ha / dopo. È ttarrivals.aspx sulla mia domanda sopra. Quindi quello sarebbe un percorso?
hichris123,

Corretta. Capita solo di essere la fine del percorso. Tecnicamente potresti mettere un "/" alla fine se lo desideri e sarebbe valido. mysite.com/path è uguale a mysite.com/path
David

1
Risposta perfetta! Questo avrebbe dovuto essere già nella documentazione dell'API.
robinmitra,

259

C'è un altro modo di usare Urie possiamo raggiungere lo stesso obiettivo

http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7

Per creare l'Uri puoi usare questo:

final String FORECAST_BASE_URL = 
    "http://api.example.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";

Puoi dichiarare tutto questo nel modo sopra o anche all'interno di Uri.parse()eappendQueryParameter()

Uri builtUri = Uri.parse(FORECAST_BASE_URL)
    .buildUpon()
    .appendQueryParameter(QUERY_PARAM, params[0])
    .appendQueryParameter(FORMAT_PARAM, "json")
    .appendQueryParameter(UNITS_PARAM, "metric")
    .appendQueryParameter(DAYS_PARAM, Integer.toString(7))
    .build();

Alla fine

URL url = new URL(builtUri.toString());

14
Ti meriti più voti! Per me, il caso d'uso di base è quando si dispone di un URL stringa già definito e si desidera aggiungere / aggiungere parametri!
lorenzo-s,

1
Stavo cercando una soluzione per sunshine (questa stringa esatta) ma la domanda più votata fornisce una soluzione molto più solida.
Nahum,

1
Grazie per il suggerimento Uri.buildUpon ()! Mi ha salvato un po 'di mal di testa.
chrjs,

Ero confuso in quale ordine sono stati creati gli URL, perché ovviamente le sue uniche variabili non sono l'URL completo, che dobbiamo fare
blackHawk

Che cosa succede se invece non ho l'URL di base ma l'URL completo? Usando Parse + BuildUpon + AppendQueryParam + Build Ottengo un URL non valido ([dominio] [queryParams] [percorso] invece di [dominio] [percorso] [queryParams])
Giuseppe Giacoppo

20

Ottima risposta dall'alto trasformata in un semplice metodo di utilità.

private Uri buildURI(String url, Map<String, String> params) {

    // build url with parameters.
    Uri.Builder builder = Uri.parse(url).buildUpon();
    for (Map.Entry<String, String> entry : params.entrySet()) {
        builder.appendQueryParameter(entry.getKey(), entry.getValue());
    }

    return builder.build();
}

Non è necessario convertire il contenuto UTF8?
Webserveis,

15

ecco un buon modo per spiegarlo:

ci sono due forme dell'URI

1 - Builder (pronto per essere modificato , non pronto per essere utilizzato )

2 - Costruito ( non pronto per essere modificato , pronto per essere utilizzato )

Puoi creare un builder da

Uri.Builder builder = new Uri.Builder();

questo restituirà un Builder pronto per essere modificato in questo modo: -

builder.scheme("https");
builder.authority("api.github.com");
builder.appendPath("search");
builder.appendPath("repositories");
builder.appendQueryParameter(PARAMETER_QUERY,parameterValue);

ma per usarlo devi prima costruirlo

retrun builder.build();

o comunque lo userai. e poi hai creato quello che è già stato creato per te, pronto per l'uso ma non può essere modificato.

Uri built = Uri.parse("your URI goes here");

questo è pronto per l'uso ma se si desidera modificarlo è necessario buildUpon ()

Uri built = Uri.parse("Your URI goes here")
           .buildUpon(); //now it's ready to be modified
           .buildUpon()
           .appendQueryParameter(QUERY_PARAMATER, parameterValue) 
           //any modification you want to make goes here
           .build(); // you have to build it back cause you are storing it 
                     // as Uri not Uri.builder

ora ogni volta che vuoi modificarlo devi buildUpon () e alla fine build () .

quindi Uri.Builder è un tipo Builder in cui è memorizzato un Builder. Uri è un tipo costruito in cui è archiviato un URI già incorporato.

nuovo Uri.Builder (); restituisce un Builder . Uri.parse ("il tuo URI va qui") restituisce un Built .

e con build () puoi cambiarlo da Builder a Built . buildUpon () puoi cambiarlo da Built a Builder . Ecco cosa puoi fare

Uri.Builder builder = Uri.parse("URL").buildUpon();
// here you created a builder, made an already built URI with Uri.parse
// and then change it to builder with buildUpon();
Uri built = builder.build();
//when you want to change your URI, change Builder 
//when you want to use your URI, use Built

e anche il contrario: -

Uri built = new Uri.Builder().build();
// here you created a reference to a built URI
// made a builder with new Uri.Builder() and then change it to a built with 
// built();
Uri.Builder builder = built.buildUpon();

spero che la mia risposta abbia aiutato :) <3


6

per l'esempio in second Answerho usato questa tecnica per lo stesso URL

http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7

Uri.Builder builder = new Uri.Builder();
            builder.scheme("https")
                    .authority("api.openweathermap.org")
                    .appendPath("data")
                    .appendPath("2.5")
                    .appendPath("forecast")
                    .appendPath("daily")
                    .appendQueryParameter("q", params[0])
                    .appendQueryParameter("mode", "json")
                    .appendQueryParameter("units", "metric")
                    .appendQueryParameter("cnt", "7")
                    .appendQueryParameter("APPID", BuildConfig.OPEN_WEATHER_MAP_API_KEY);

poi dopo aver finito di costruirlo prendilo URLcosì

URL url = new URL(builder.build().toString());

e aprire una connessione

  HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

e se il collegamento è simplesimile alla posizione uri, ad esempio

geo:0,0?q=29203

Uri geoLocation = Uri.parse("geo:0,0?").buildUpon()
            .appendQueryParameter("q",29203).build();

2
URL url = new URL(builder.build().toString());deve concludere un tentativo di cattura per MalformedURLException
Ali Kazi il

2

L'utilizzo appendEncodePath()potrebbe farti risparmiare più righe di appendPath(), il seguente frammento di codice crea questo url:http://api.openweathermap.org/data/2.5/forecast/daily?zip=94043

Uri.Builder urlBuilder = new Uri.Builder();
urlBuilder.scheme("http");
urlBuilder.authority("api.openweathermap.org");
urlBuilder.appendEncodedPath("data/2.5/forecast/daily");
urlBuilder.appendQueryParameter("zip", "94043,us");
URL url = new URL(urlBuilder.build().toString());

2

Migliore risposta: https://stackoverflow.com/a/19168199/413127

Esempio per

 http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7

Ora con Kotlin

 val myUrl = Uri.Builder().apply {
        scheme("https")
        authority("www.myawesomesite.com")
        appendPath("turtles")
        appendPath("types")
        appendQueryParameter("type", "1")
        appendQueryParameter("sort", "relevance")
        fragment("section-name")
        build()            
    }.toString()

Grazie per aver aggiunto la versione di Kotlin :)
M Mansour il

0

Puoi farlo con le espressioni lambda;

    private static final String BASE_URL = "http://api.example.org/data/2.5/forecast/daily";

    private String getBaseUrl(Map<String, String> params) {
        final Uri.Builder builder = Uri.parse(BASE_URL).buildUpon();
        params.entrySet().forEach(entry -> builder.appendQueryParameter(entry.getKey(), entry.getValue()));
        return builder.build().toString();
    }

e puoi creare parametri come quello;

    Map<String, String> params = new HashMap<String, String>();
    params.put("zip", "94043,us");
    params.put("units", "metric");

Btw. In caso di problemi come questi “lambda expressions not supported at this language level”, controlla questo URL;

https://stackoverflow.com/a/22704620/2057154

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.