在Android中使用URI构建器或使用变量创建URL


202

我正在开发一个Android应用程序。我需要为我的应用程序构建一个URI,以发出API请求。除非有另一种将变量放入URI的方法,否则这是我找到的最简单的方法。我发现您需要使用Uri.Builder,但是我不确定如何使用。我的网址是:

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吗?

Answers:


426

假设我要创建以下网址:

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/pathmysite.com/path
David

1
完美的答案!这应该已经在API文档中了。
robinmitra 2015年

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 2015年

1
我一直在寻找一种解决阳光的解决方案(此确切的字符串),但投票最多的问题提供了更为可靠的解决方案。
Nahum 2015年

1
感谢您的Uri.buildUpon()提示!救了我一些头疼。
chrjs '16

我对按什么顺序创建URL感到困惑,因为当然它必须唯一的变量而不是完整的URL
blackHawk

如果我没有基本网址,而是完整网址,该怎么办?使用Parse + BuildUpon + AppendQueryParam + Build,我得到一个无效的网址([domain] [queryParams] [path]而不是[domain] [path] [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-生成器(准备修改尚未准备好使用

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.Builder(); 重新召集一名建造者Uri.parse(“您的URI到这里”)返回一个Built

并通过build()将其从Builder更改为BuiltbuildUpon()可以将其从Built更改为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我在同一网址中使用此技术的示例

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(),以下代码段构建了该网址: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版本:)
M Mansour

0

您可以使用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();
    }

您可以创建类似的参数;

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

顺便说一句。如果您会遇到类似的问题“lambda expressions not supported at this language level”,请检查此网址;

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.