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.