Используйте конструктор 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
Дэвид

1
Идеальный ответ! Это должно было быть уже в документации API.
Робинмитра

260

Существует другой способ использования, 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());

15
Вы заслуживаете больше голосов! Для меня основной вариант использования - это когда у вас уже есть определенный строковый URL, и вы хотите добавить / добавить параметры!
Лоренцо-с

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

1
Спасибо за подсказку Uri.buildUpon ()! Избавил меня от головной боли.
chrjs

Я был озадачен тем, в каком порядке создаются URL-
адреса

Что делать, если у меня нет базового URL, а вместо этого полный URL? Используя Parse + BuildUpon + AppendQueryParam + Build, я получаю недопустимый URL-адрес ([домен] [queryParams] [путь] вместо [домен] [путь] [queryParams])
Джузеппе Джакоппо

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 - Строитель (готов к модификации , не готов к использованию )

2 - Построен ( не готов к модификации , готов к использованию )

Вы можете создать застройщика

Uri.Builder builder = new Uri.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 (); rerurns Builder . Uri.parse («ваш URI идет сюда») возвращает Built .

и с помощью build () вы можете изменить его с Builder на Built . buildUpon () вы можете изменить его со встроенного на строительный . Вот что вы можете сделать

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());должен быть обернут блоком try catch для 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

Теперь с 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()

Спасибо за добавление версии Kotlin :)
М Мансур

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.