Використовуйте конструктор URI в Android або створюйте URL із змінними


202

Я розробляю додаток для Android. Мені потрібно створити URI для свого додатка, щоб зробити запит API. Якщо немає іншого способу ввести змінну в URI, це найпростіший спосіб, який я знайшов. Я виявив, що вам потрібно користуватися Uri.Builder, але я не зовсім впевнений, як це зробити. Моя URL-адреса:

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

Моя схема http, повноваження є lapi.transitchicago.com, шлях є /api/1.0, сегмент (и) шляху є ttarrivals.aspx, а рядок запиту - key=[redacted]&mapid=value.

Мій код нижче:

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

Я розумію, що я можу зробити URI.add, але як я інтегрувати його до програми Uri.Builder? Повинен чи я додати всі , як URI.add(scheme), URI.add(authority)і так далі? Або це не спосіб зробити це? Також, чи є інший простіший спосіб додати змінну до URI / URL?

Відповіді:


426

Скажімо, я хочу створити таку URL-адресу:

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

Щоб побудувати це за допомогою Uri.Builderя, я зробив би наступне.

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
З мого сегменту шляху це був би шлях? Або це був би запит?
— hichris123

Якщо це шлях, то це був би appendPath()метод. Якщо це рядок запиту (приходить після?), Тоді використовуйте appendQueryParameter(). Погляньте на URL-адресу, яку я маю на прикладі, і що я роблю з кожним сегментом. Я також додав toString()до build()дзвінка, щоб повернути належний тип.
— Девід

1
Це перед знаком питання, але він не має / після нього. На моє запитання вище це ttarrivals.aspx. Так це був би шлях?
— hichris123

Правильно. Це просто буває в кінці шляху. Технічно ви можете поставити "/" в кінці, якщо хочете, і це було б дійсно. mysite.com/path - це те саме, що і mysite.com/path
— David

1
Ідеальна відповідь! Це повинно бути вже в документації API.
— robinmitra

259

Є ще один спосіб використання, Uriі ми можемо досягти тієї ж мети

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

Для створення Uri ви можете скористатися цим:

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";

Ви можете заявити про все це вище, або навіть усередині Uri.parse()таappendQueryParameter()

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

Нарешті

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

14
Ти заслужив більше голосів! Для мене основним випадком використання є те, коли у вас вже визначена рядкова URL-адреса, і ви хочете додати / додати параметри!
— lorenzo-s

1
Я шукав рішення для сонячного світла (саме ця струна), але найбільш проголосоване питання забезпечує набагато більш надійне рішення.
— Навум

1
Дякуємо за підказку Uri.buildUpon ()! Врятував мені деякі головні болі.
— chrjs

Я був розгублений у тому, в якому порядку створюються URL-адреси, оскільки, звичайно, його єдині змінні, а не повна URL-адреса, яку ми маємо зробити
— blackHawk

Що робити, якщо у мене немає базового URL-адреси, а повного URL-адреса? Використовуючи Parse + BuildUpon + AppendQueryParam + Build, я отримую недійсний URL ([домен] [queryParams] [шлях] замість [домен] [шлях] [queryParams])
— Giuseppe Giacoppo

20

Відмінна відповідь зверху перетворилася на простий корисний метод.

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

Не потрібно конвертувати вміст UTF8?
— Webserveis

15

ось хороший спосіб пояснити це:

є дві форми URI

1 - Builder (готовий до модифікації , не готовий до використання )

2 - Вбудований ( не готовий до модифікації , готовий до використання )

Ви можете створити будівельника за допомогою

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

це поверне Builder готовий до модифікації так: -

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

але щоб використовувати його, потрібно спочатку побудувати його

retrun builder.build();

або як би ти не користувався ним. а потім ви створили те, що вже побудоване для вас, готове до використання, але не може бути змінене.

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

це готово до використання, але якщо ви хочете змінити його, вам потрібно 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

тепер кожного разу, коли ви хочете його змінювати, вам потрібно buildUpon () і, врешті, build () .

тому Uri.Builder - це тип Builder, який зберігає в ньому Builder. Uri - тип Вбудований, який зберігає в ньому вже вбудований URI.

новий Uri.Builder (); повертає будівельника . Uri.parse ("ваш URI йде сюди") повертає вбудований .

а за допомогою build () ви можете змінити його з Builder на Built . buildUpon () ви можете змінити його з вбудованого в Builder . Ось що ви можете зробити

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

а також навпаки: -

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

сподіваюся, моя відповідь допомогла :) <3


6

наприклад, second Answerя використав цю методику для тієї ж 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);

то після того, як добудовувати його отримати як URLтак

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

і відкрити з'єднання

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

і якщо, наприклад, посилання simpleнагадує розташування uri

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());має завершити блок спробу лову для MalformedURLException
— Алі Казі

2

Використання appendEncodePath()може врятувати вас декілька рядків, ніж appendPath()цей фрагмент коду створює цю 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

Найкраща відповідь: https://stackoverflow.com/a/19168199/413127

Приклад для

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

Тепер з Котліном

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

Дякуємо, що додали версію Котліна :)
— M Mansour

0

Це можна зробити за допомогою лямбда-виразів;

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

і ви можете створити подібні парами;

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

Btw. Якщо у вас виникне будь-яке питання “lambda expressions not supported at this language level”, будь ласка, перевірте цю URL-адресу;

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.