Verwenden Sie den URI Builder in Android oder erstellen Sie eine URL mit Variablen

202

Ich entwickle eine Android App. Ich muss einen URI für meine App erstellen, um eine API-Anfrage zu stellen. Dies ist der einfachste Weg, den ich gefunden habe, es sei denn, es gibt eine andere Möglichkeit, eine Variable in eine URI einzufügen. Ich habe festgestellt, dass Sie verwenden müssen Uri.Builder, aber ich bin nicht ganz sicher, wie. Meine URL lautet:

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

Mein Schema ist http, Autorität ist lapi.transitchicago.com, Pfad ist /api/1.0, Pfadsegment (e) ist ttarrivals.aspxund Abfragezeichenfolge ist key=[redacted]&mapid=value.

Mein Code ist unten:

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

Ich verstehe, dass ich es kann URI.add, aber wie integriere ich es in die Uri.Builder? Soll ich alles wie hinzufügen URI.add(scheme), URI.add(authority)und so weiter? Oder ist das nicht der richtige Weg? Gibt es auch eine andere einfachere Möglichkeit, einer URI / URL eine Variable hinzuzufügen?

hichris123
quelle

Antworten:

426

Angenommen, ich möchte die folgende URL erstellen:

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

Um dies mit dem zu bauen, Uri.Builderwürde ich folgendes tun.

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
quelle
1
Wäre es mit meinem Pfadsegment ein Pfad? Oder wäre es eine Frage?
hichris123
Wenn es ein Pfad ist, dann wäre es appendPath()für die Methode. Wenn es sich um eine Abfragezeichenfolge handelt (nach dem?), Verwenden Sie appendQueryParameter(). Schauen Sie sich die URL an, die ich im Beispiel habe, und was ich mit jedem Segment mache. Ich toString()habe dem build()Anruf auch hinzugefügt , um den richtigen Typ zurückzubekommen.
David
1
Es ist vor dem Fragezeichen, aber es hat kein / danach. Es ist ttarrivals.aspx auf meine Frage oben. Das wäre also ein Weg?
hichris123
Richtig. Es ist einfach das Ende des Weges. Technisch gesehen könnten Sie am Ende ein "/" setzen, wenn Sie möchten, und es wäre gültig. mysite.com/path ist das gleiche wie mysite.com/path
David
1
Perfekte Antwort! Dies sollte bereits in der API-Dokumentation enthalten sein.
Robinmitra
259

Es gibt eine andere Art der Verwendung Uriund wir können das gleiche Ziel erreichen

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

Um den Uri zu bauen, können Sie Folgendes verwenden:

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

Sie können dies alles auf die oben beschriebene Weise oder sogar innerhalb des Uri.parse()und deklarierenappendQueryParameter()

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

Zu guter Letzt

URL url = new URL(builtUri.toString());
Amit Tripathi
quelle
14
Sie verdienen mehr Stimmen! Für mich ist der grundlegende Anwendungsfall, wenn Sie eine bereits definierte Zeichenfolgen-URL haben und Parameter hinzufügen / anhängen möchten!
Lorenzo-s
1
Ich suchte nach einer Lösung für Sonnenschein (genau diese Zeichenfolge), aber die am häufigsten gestellte Frage bietet eine viel robustere Lösung.
Nahum
1
Vielen Dank für den Hinweis auf Uri.buildUpon ()! Hat mir Kopfschmerzen erspart.
Chrjs
Ich war verwirrt, in welcher Reihenfolge die URL erstellt wird, da es sich natürlich nur um die vollständige URL handelt, die wir
erstellen
Was ist, wenn ich nicht die Basis-URL, sondern die vollständige URL habe? Mit Parse + BuildUpon + AppendQueryParam + Build erhalte ich eine ungültige URL ([domain] [queryParams] [path] anstelle von [domain] [path] [queryParams])
Giuseppe Giacoppo
20

Die hervorragende Antwort von oben wurde zu einer einfachen Dienstprogrammmethode.

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
quelle
Keine Notwendigkeit, UTF8-Inhalte zu konvertieren?
Webserveis
15

Hier ist ein guter Weg, um es zu erklären:

Es gibt zwei Formen der URI

1 - Builder (bereit zur Änderung , nicht zur Verwendung bereit )

2 - Gebaut ( nicht bereit, geändert zu werden , bereit, verwendet zu werden )

Sie können einen Builder erstellen mit

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

Dies wird einen Builder zurückgeben, der bereit ist, wie folgt geändert zu werden: -

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

Aber um es zu benutzen, muss man es zuerst bauen

retrun builder.build();

oder wie auch immer du es benutzen wirst. und dann haben Sie erstellt, das bereits für Sie erstellt wurde, einsatzbereit ist, aber nicht geändert werden kann.

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

Dies ist gebrauchsfertig, aber wenn Sie es ändern möchten, müssen Sie 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

Jetzt müssen Sie jedes Mal, wenn Sie es ändern möchten, buildUpon () und am Ende build () .

so Uri.Builder ist ein Builder - Typ , die in ihm einen Builder speichern. Uri ist ein Gebautes Typ, in dem eine bereits erstellte URI gespeichert ist.

neuer Uri.Builder (); gibt einen Builder zurück . Uri.parse ("Ihr URI geht hierher") gibt einen Built zurück .

und mit build () können Sie es von Builder in Built ändern . buildUpon () können Sie von Built in Builder ändern . Hier ist was Sie tun können

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

und auch das Gegenteil: -

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

hoffe meine antwort hat geholfen :) <3

Mina Shaker
quelle
6

Für das Beispiel im habe second Answerich diese Technik für dieselbe URL verwendet

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

dann nach dem Fertiggebäude bekommen sie es als URLwie diese

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

und öffnen Sie eine Verbindung

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

und wenn link simplewie location uri ist, zum Beispiel

geo:0,0?q=29203

Uri geoLocation = Uri.parse("geo:0,0?").buildUpon()
            .appendQueryParameter("q",29203).build();
Basheer AL-MOMANI
quelle
2
URL url = new URL(builder.build().toString());muss von einem Try Catch Block für MalformedURLException
Ali Kazi
2

Wenn Sie appendEncodePath()verwenden, können Sie mehrere Zeilen sparen, als appendPath()das folgende Codefragment diese URL erstellt: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
quelle
2

Beste Antwort: https://stackoverflow.com/a/19168199/413127

Beispiel für

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

Jetzt mit 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()
Blundell
quelle
Vielen Dank für das Hinzufügen der Kotlin-Version :)
M Mansour
0

Sie können dies mit Lambda-Ausdrücken tun.

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

und Sie können solche Parameter erstellen;

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

Übrigens. Wenn Sie auf ein Problem wie “lambda expressions not supported at this language level”dieses stoßen, überprüfen Sie bitte diese URL;

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

Yusuf
quelle