Використовуйте конструктор 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.