Android'de URI oluşturucuyu kullanma veya değişkenlerle URL oluşturma


204

Bir Android uygulaması geliştiriyorum. Bir API isteği yapmak için uygulamam için bir URI oluşturmam gerekiyor. Bir değişkeni bir URI'ye koymanın başka bir yolu yoksa, bulduğum en kolay yol budur. Kullanmanız gerektiğini buldum Uri.Builder, ama nasıl yapacağınızdan emin değilim. URL’m:

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

Şemam http, yetki lapi.transitchicago.com, yol /api/1.0, yol segment (ler) i ttarrivals.aspxve sorgu dizesi key=[redacted]&mapid=value.

Kodum aşağıda:

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

Yapabileceğimi anlıyorum URI.add, ama bunu nasıl entegre edebilirim Uri.Builder? Gibi her şeyi eklemeli miyim URI.add(scheme), URI.add(authority)vs. Yoksa bunu yapmanın yolu değil mi? Ayrıca, bir URI / URL'ye değişken eklemenin daha kolay bir yolu var mı?

Yanıtlar:


428

Aşağıdaki URL'yi oluşturmak istediğimi varsayalım:

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

Bunu inşa etmek Uri.Builderiçin aşağıdakileri yaparım.

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
Yol bölümümle bir yol olur mu? Yoksa bir sorgu mu?
hichris123

Bir yolsa, appendPath()yöntem için olurdu . Bir sorgu dizesi ise (? Sonra geliyor) kullanın appendQueryParameter(). Örnekte sahip olduğum URL'ye ve her bir segmentle ne yaptığımı inceleyin. Ben de eklendi toString()için build()uygun tip geri almak için çağrı.
David

1
Soru işaretinden önce, ama bir / sonrasına sahip değil. Yukarıdaki sorumla ilgili ttarrivals.aspx. Yani bu bir yol mudur?
hichris123

Doğru. Sadece yolun sonu oluyor. İsterseniz teknik olarak sonuna bir "/" koyabilirsiniz ve geçerli olur. mysite.com/path aynıdır mysite.com/path
David

1
Mükemmel cevap! Bu, API belgelerinde zaten bulunmalıydı.
robinmitra

262

Kullanmanın başka bir yolu var Urive aynı hedefe ulaşabiliriz

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

Uri'yi oluşturmak için bunu kullanabilirsiniz:

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

Tüm bu yukarıda yolu beyan veya hatta iç Uri.parse()veappendQueryParameter()

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

Sonunda

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

15
Daha fazla oy hak ediyorsun! Benim için temel kullanım durumu, daha önce tanımlanmış bir dize URL'niz olduğunda ve parametre eklemek / eklemek istediğiniz zamandır!
lorenzo-s

1
Güneş ışığı için bir çözüm arıyordum (bu tam dize) ama en çok oy alan soru çok daha sağlam bir çözüm sunuyor.
Nahum

1
Uri.buildUpon () ipucu için teşekkürler! Bana bazı baş ağrılarını kurtardı.
chrjs

Hangi sipariş URL'sinin yapıldığı konusunda kafam karıştı, çünkü elbette tek değişkeni tam URL değil, yapmak zorundayız
blackHawk

Bunun yerine temel URL’m yok ama bunun yerine tam URL’m varsa ne olur? Ayrıştırma + BuildUpon + AppendQueryParam + Build kullanma [domain] [path] [queryParams] yerine geçerli olmayan bir url ([domain] [queryParams] [path] alıyorum
Giuseppe Giacoppo

21

Yukarıdan gelen mükemmel cevap basit bir fayda yöntemine dönüştü.

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 içeriğini dönüştürmeye gerek yok mu?
Webserveis

16

İşte bunu açıklamanın iyi bir yolu:

URI'nin iki formu vardır

1 - Oluşturucu (hazır değiştirilmiş , değil hazır hale gelmesini kullanılır )

2 - Dahili ( değiştirilmeye hazır değil , kullanılmaya hazır )

Tarafından bir oluşturucu oluşturabilirsiniz

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

bu , aşağıdaki gibi değiştirilmeye hazır bir Builder döndürecektir : -

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

ama kullanmak için önce onu inşa etmelisin

retrun builder.build();

ya da onu kullanacaksın. ve sonra gelmiş inşa zaten kullanıma hazır, sizin için oluşturulmuştur ancak değiştirilemez söyledi.

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

bu kullanıma hazırdır ancak değiştirmek isterseniz 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

şimdi her değişiklik yapmak istediğinizde buildUpon () ve sonunda build () .

böylece Uri.Builder bir olduğunu Oluşturucu içinde bir Builder saklamak türü. Uri , içinde zaten oluşturulmuş bir URI saklayan bir Dahili türdür.

yeni Uri.Builder (); bir Builder döndürür . Uri.parse ("URI'niz buraya gelir") bir Built döndürür .

ve birlikte yapı () sen onu değiştirebilirsiniz Builder için inşa edilen . buildUpon () den bunu değiştirebilirsiniz Dahili için Builder . İşte yapabilecekleriniz

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

ve tam tersi: -

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

Umarım cevabım yardımcı oldu :) <3


6

second Answeraynı URL için bu tekniği kullandığım örnek için

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

Daha sonra bitiş bina sonra o kadar olsun URLböyle

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

ve bir bağlantı aç

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

ve bağlantı simplekonum uri'ye benziyorsa, örneğin

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()); MalformedURLException için bir try catch bloğu ile sarılmalıdır
Ali Kazi

2

Kullanmak appendEncodePath()size daha fazla satır kaydedebilir appendPath(), aşağıdaki kod snippet'i bu URL'yi oluşturur: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

En iyi cevap: https://stackoverflow.com/a/19168199/413127

İçin örnek

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

Şimdi Kotlin ile

 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 versiyonunu eklediğiniz için teşekkür ederiz :)
M Mansour

0

Bunu lambda ifadeleriyle yapabilirsiniz;

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

ve bunun gibi parametreler yaratabilirsiniz;

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

Btw. Gibi herhangi bir sorunla karşılaşırsanız“lambda expressions not supported at this language level” , lütfen bu URL'yi kontrol edin;

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.