Sử dụng trình tạo URI trong Android hoặc tạo URL với các biến


202

Tôi đang phát triển một ứng dụng Android. Tôi cần xây dựng URI cho ứng dụng của mình để thực hiện yêu cầu API. Trừ khi có một cách khác để đặt một biến trong URI, đây là cách dễ nhất mà tôi đã tìm thấy. Tôi thấy rằng bạn cần phải sử dụng Uri.Builder, nhưng tôi không chắc chắn làm thế nào để. Url của tôi là:

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

Lược đồ của tôi là http, thẩm quyền là lapi.transitchicago.com, đường dẫn là /api/1.0, (các) đoạn đường dẫn ttarrivals.aspxvà chuỗi truy vấn là key=[redacted]&mapid=value.

Mã của tôi dưới đây:

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

Tôi hiểu rằng tôi có thể làm được URI.add, nhưng làm cách nào để tích hợp nó vào Uri.Builder? Tôi có nên thêm mọi thứ như thế URI.add(scheme), URI.add(authority)v.v. Hay đó không phải là cách để làm điều đó? Ngoài ra, có cách nào khác dễ dàng hơn để thêm một biến vào URI / URL không?

Câu trả lời:


426

Hãy nói rằng tôi muốn tạo URL sau:

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

Để xây dựng điều này với Uri.Buildertôi sẽ làm như sau.

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
Với đoạn đường dẫn của tôi, nó sẽ là một con đường? Hay nó sẽ là một truy vấn?
hichris123

Nếu nó là một đường dẫn, thì nó sẽ appendPath()dành cho phương thức. Nếu đó là một chuỗi truy vấn (đến sau?) Thì sử dụng appendQueryParameter(). Hãy xem URL mà tôi có trong ví dụ và những gì tôi đang làm với từng phân khúc. Tôi cũng đã thêm toString()vào build()cuộc gọi để có được những loại lại thích hợp.
David

1
Đó là trước dấu chấm hỏi, nhưng nó không có / sau nó. Đó là ttarrivals.aspx cho câu hỏi của tôi ở trên. Vì vậy, đó sẽ là một con đường?
hichris123

Chính xác. Nó chỉ là kết thúc của con đường. Về mặt kỹ thuật, bạn có thể đặt "/" ở cuối nếu bạn muốn và nó sẽ hợp lệ. mysite.com/path giống như mysite.com/path
David

1
Câu trả lời hoàn hảo! Điều này đã có trong tài liệu API rồi.
robinmitra 7/12/2015

259

Có một cách sử dụng khác Urivà chúng ta có thể đạt được cùng một mục tiêu

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

Để xây dựng Uri, bạn có thể sử dụng:

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

Bạn có thể khai báo tất cả điều này theo cách trên hoặc thậm chí bên trong 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();

Cuối cùng

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

14
Bạn xứng đáng được nhiều phiếu hơn! Đối với tôi, trường hợp sử dụng cơ bản là khi bạn có URL chuỗi đã được xác định và bạn muốn thêm / nối các tham số!
lorenzo-s

1
Tôi đang tìm kiếm một giải pháp cho ánh nắng mặt trời (chuỗi chính xác này) nhưng câu hỏi được bình chọn nhiều nhất cung cấp giải pháp mạnh mẽ hơn nhiều.
Nahum

1
Cảm ơn gợi ý của Uri.buildUpon ()! Cứu tôi một số đau đầu.
chrjs

Tôi đã nhầm lẫn về thứ tự url được tạo ra, bởi vì tất nhiên các biến duy nhất của nó không phải là url hoàn chỉnh, mà chúng ta phải thực hiện
blackHawk

Nếu tôi không có url cơ sở nhưng thay vào đó là url hoàn chỉnh thì sao? Sử dụng Parse + BuildUpon + AppendQueryParam + Build Tôi nhận được một url không hợp lệ ([domain] [queryParams] [path] thay vì [domain] [path] [queryParams])
Giuseppe Giacoppo

20

Câu trả lời tuyệt vời từ trên biến thành một phương pháp tiện ích đơn giản.

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

Không cần chuyển đổi nội dung UTF8?
Webserveis

15

Đây là một cách tốt để giải thích nó:

có hai dạng của URI

1 - Trình tạo (sẵn sàng sửa đổi , chưa sẵn sàng để sử dụng )

2 - Được xây dựng ( chưa sẵn sàng để sửa đổi , sẵn sàng để sử dụng )

Bạn có thể tạo một trình xây dựng bằng cách

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

điều này sẽ trả về một Builder đã sẵn sàng để được sửa đổi như thế này: -

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

nhưng để sử dụng nó, bạn phải xây dựng nó trước

retrun builder.build();

hoặc tuy nhiên bạn sẽ sử dụng nó. và sau đó bạn đã xây dựng đã được xây dựng cho bạn, sẵn sàng để sử dụng nhưng không thể sửa đổi.

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

cái này đã sẵn sàng để sử dụng nhưng nếu bạn muốn sửa đổi nó, bạn cần 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

bây giờ mỗi khi bạn muốn sửa đổi nó, bạn cần buildUpon () và cuối cùng là build () .

vì vậy Uri.Builder là loại Builder lưu trữ Builder trong đó. Uri là loại Được xây dựng lưu trữ URI đã được xây dựng trong đó.

Uri.Builder mới (); quay lại một Builder . Uri.parse ("URI của bạn ở đây") trả về Đã xây dựng .

và với xây dựng () , bạn có thể thay đổi nó từ Builder để xây dựng . buildUpon () bạn có thể thay đổi nó từ Được xây dựng thành Builder . Dưới đây là những gì bạn có thể làm

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

và cũng ngược lại: -

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

hy vọng câu trả lời của tôi đã giúp :) <3


6

ví dụ trong second Answertôi đã sử dụng kỹ thuật này cho cùng một 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);

Sau khi xây dựng xong, nó sẽ như URLthế này

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

và mở một kết nối

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

và nếu liên kết simplegiống như vị trí uri, ví dụ

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());phải được bao bọc bởi một khối thử bắt cho MalformedURLException
Ali Kazi

2

Việc sử dụng appendEncodePath()có thể giúp bạn tiết kiệm nhiều dòng hơn appendPath(), đoạn mã sau đây sẽ tạo ra url này: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

Câu trả lời hay nhất: https://stackoverflow.com/a/19168199/413127

Ví dụ như

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

Bây giờ với 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()

Cảm ơn bạn đã thêm phiên bản Kotlin :)
M Mansour

0

Bạn có thể làm điều đó với các biểu thức 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();
    }

và bạn có thể tạo các thông số như thế;

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

Btw. Nếu bạn sẽ phải đối mặt với bất kỳ vấn đề nào như “lambda expressions not supported at this language level”, vui lòng kiểm tra URL này;

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.