Użyj konstruktora URI w systemie Android lub utwórz adres URL ze zmiennymi


202

Tworzę aplikację na Androida. Muszę zbudować identyfikator URI dla mojej aplikacji, aby wykonać żądanie interfejsu API. O ile nie ma innego sposobu na umieszczenie zmiennej w URI, jest to najłatwiejszy sposób, jaki znalazłem. Odkryłem, że musisz użyć Uri.Builder, ale nie jestem pewien, jak to zrobić. Mój adres URL to:

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

Mój schemat to http, autorytet lapi.transitchicago.com, ścieżka to /api/1.0, segmenty ścieżki to ttarrivals.aspx, a ciąg zapytania to key=[redacted]&mapid=value.

Mój kod jest poniżej:

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

Rozumiem, że mogę to zrobić URI.add, ale jak mogę to zintegrować z Uri.Builder? Dodam wszystko podobnego URI.add(scheme), URI.add(authority)i tak dalej? A może nie tak to zrobić? Czy istnieje też inny łatwiejszy sposób dodania zmiennej do identyfikatora URI / adresu URL?

Odpowiedzi:


426

Powiedzmy, że chcę utworzyć następujący adres URL:

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

Aby zbudować to za pomocą Uri.Builder, zrobiłbym następujące.

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
Czy z moim segmentem ścieżki byłaby to ścieżka? A może byłoby to zapytanie?
— hichris123

Jeśli jest to ścieżka, byłaby to appendPath()metoda. Jeśli jest to ciąg zapytania (występujący po?), Użyj appendQueryParameter(). Spójrz na adres URL, który mam w przykładzie i co robię z każdym segmentem. Dodałem również toString()do build()połączenia, aby odzyskać odpowiedni typ.
— David

1
Jest przed znakiem zapytania, ale nie ma znaku / po nim. To jest ttarrivals.aspx na moje pytanie powyżej. To byłaby ścieżka?
— hichris123

Poprawny. To po prostu koniec ścieżki. Technicznie możesz umieścić „/” na końcu, jeśli chcesz i byłoby to ważne. mysite.com/path jest taki sam jak mysite.com/path
— David

1
Idealna odpowiedź! Powinno to już być w dokumentacji API.
— robinmitra,

259

Jest inny sposób korzystania Urii możemy osiągnąć ten sam cel

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

Aby zbudować Uri, możesz użyć tego:

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

Możesz to wszystko zadeklarować w powyższy sposób, a nawet wewnątrz Uri.parse()iappendQueryParameter()

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

W końcu

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

14
Zasługujesz na więcej głosów! Dla mnie podstawowym przypadkiem użycia jest sytuacja, gdy masz już zdefiniowany adres URL ciągu i chcesz dodać / dołączyć parametry!
— lorenzo-s

1
Szukałem rozwiązania dla słońca (dokładnie ten ciąg), ale najczęściej głosowane pytanie zapewnia znacznie bardziej niezawodne rozwiązanie.
— Nahum,

1
Dzięki za podpowiedź Uri.buildUpon ()! Zaoszczędził mi ból głowy.
— chrjs,

Byłem zdezorientowany, w jakiej kolejności jest tworzony adres URL, ponieważ oczywiście jedynymi zmiennymi nie jest pełny adres URL, który musimy utworzyć
— blackHawk

Co jeśli nie mam podstawowego adresu URL, ale pełny adres URL? Za pomocą narzędzia Parse + BuildUpon + AppendQueryParam + Build otrzymuję niepoprawny adres URL ([domena] [queryParams] [ścieżka] zamiast [domena] [ścieżka] [queryParams])
— Giuseppe Giacoppo

20

Doskonała odpowiedź z góry zamieniła się w prostą metodę użyteczności.

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

Nie musisz konwertować treści UTF8?
— Webserveis,

15

oto dobry sposób na wyjaśnienie:

istnieją dwie formy identyfikatora URI

1 - Konstruktor (gotowy do modyfikacji , nie gotowy do użycia )

2 - Wbudowany ( nie gotowe do modyfikowany , gotowe mają być używane )

Możesz utworzyć konstruktora przez

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

zwróci to Konstruktora gotowego do modyfikacji w następujący sposób: -

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

ale aby go użyć, musisz go najpierw zbudować

retrun builder.build();

lub jakkolwiek go użyjesz. a następnie został zbudowany , że jest już zbudowany dla Ciebie, gotowy do użycia, ale nie mogą być modyfikowane.

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

jest gotowy do użycia, ale jeśli chcesz go zmodyfikować, musisz 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

teraz za każdym razem, gdy chcesz go zmodyfikować, musisz buildUpon () i na końcu build () .

więc Uri.Builder jest typem Konstruktora, który przechowuje w nim Konstruktora. Uri to typ zbudowany, który przechowuje w nim już zbudowany identyfikator URI.

new Uri.Builder (); przywraca Konstruktora . Uri.parse („Twój URI idzie tutaj”) zwraca wartość Built .

i budowy () można zmienić z Builder do Wbudowany . buildUpon () można zmienić go od Zbudowany do Builder . Oto, co możesz zrobić

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

i odwrotnie:

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

mam nadzieję, że moja odpowiedź pomogła :) <3


6

na przykład w second Answerużyłem tej techniki dla tego samego adresu 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);

potem po ukończeniu budowy otrzymaj to w URLten sposób

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

i otwórz połączenie

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

i jeśli simplena przykład link jest podobny do lokalizacji 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());musi zostać owinięty blokiem catch dla MalformedURLException
— Ali Kazi

2

Użycie appendEncodePath()może zaoszczędzić wiele linii niż appendPath(), następujący fragment kodu tworzy ten adres 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

Najlepsza odpowiedź: https://stackoverflow.com/a/19168199/413127

Przykład dla

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

Teraz z Kotlinem

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

Dziękujemy za dodanie wersji Kotlin :)
— M Mansour

0

Możesz to zrobić za pomocą wyrażeń 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();
    }

i możesz tworzyć takie parametry;

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

Btw. Jeśli napotkasz jakikolwiek problem “lambda expressions not supported at this language level”, sprawdź ten adres URL;

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.