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?

hichris123
źródło

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();
David
źródło
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());
Amit Tripathi
źródło
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();
}
Chris
źródło
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

Mina Shaker
źródło
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();
Basheer AL-MOMANI
źródło
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());
Cody
źródło
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()
Blundell
źródło
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

yusuf
źródło