AndroidでURIビルダーを使用するか、変数を使用してURLを作成する


202

Androidアプリを開発しています。アプリがAPIリクエストを行うためのURIを構築する必要があります。URIに変数を配置する別の方法がない限り、これが私が見つけた最も簡単な方法です。を使用する必要があることがわかりましたが、使用Uri.Builder方法がよくわかりません。私のURLは:

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

私のスキームはhttp、権限はlapi.transitchicago.com、パスは/api/1.0、パスセグメントはttarrivals.aspx、クエリ文字列はkey=[redacted]&mapid=valueです。

私のコードは以下です:

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

できることはわかっていますがURI.add、どうやって統合するのUri.Builderですか?私のようなすべてのものを追加する必要がありURI.add(scheme)URI.add(authority)上とそうか?それともそれを行う方法ではありませんか?また、URI / URLに変数を追加する簡単な方法は他にありますか?

回答:


426

次のURLを作成するとします。

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

これをビルドUri.Builderするには、次のようにします。

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
私のパスセグメントでは、それはパスでしょうか?それともクエリでしょうか?
hichris123 2013年

パスの場合、それはappendPath()メソッド用です。クエリ文字列(?の後に来る)の場合は、を使用しますappendQueryParameter()。例にあるURLと、各セグメントで何をしているのか見てみましょう。適切なタイプを取り戻すための呼び出しにも追加toString()しましたbuild()
David

1
疑問符の前にありますが、後に/がありません。上記の質問のttarrivals.aspxです。だからそれは道でしょうか?
hichris123 2013年

正しい。それはたまたまパスの終わりです。技術的には、必要に応じて末尾に「/」を付けることができ、それが有効になります。 mysite.com/pathmysite.com/pathと同じです
David

1
完璧な答えです!これはAPIドキュメントにすでに含まれているはずです。
robinmitra

259

別の使用方法がありUri、同じ目標を達成できます

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

Uriをビルドするには、これを使用できます。

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

あなたは上記の方法でこのすべてを宣言したり、内部にすることができます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();

やっと

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

14
あなたはもっと投票に値します!私にとって、基本的なユースケースは、すでに定義された文字列URLがあり、パラメーターを追加/追加したい場合です!
lorenzo-s

1
私は太陽の光(この文字列)の解決策を探していましたが、最も投票された質問ははるかに堅牢な解決策を提供します。
ナフム2015

1
Uri.buildUpon()ヒントをありがとう!私はいくつかの頭痛を救った。
chrjs

もちろん、完全なURLではなく変数のみを作成する必要があるため、URLの作成順序に混乱が
生じました

ベースURLではなく完全なURLがない場合はどうなりますか?Parse + BuildUpon + AppendQueryParam + Buildを使用すると、無効なURL([domain] [path] [queryParams]ではなく[domain] [queryParams] [path])が表示されます
Giuseppe Giacoppo

20

上からの素晴らしい答えは、単純な実用的な方法に変わりました。

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コンテンツを変換する必要はありませんか?
Webserveis 2017

15

これはそれを説明する良い方法です:

URIには2つの形式があります

1 -ビルダー(する準備変性しない準備ができて使用

2 -築(ないこと準備ができ変性、される準備ができて使用

あなたはビルダーを作成することができます

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

これは、次のように変更する準備ができたビルダーを返します:-

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

しかし、それを使用するには、最初にそれを構築する必要があります

retrun builder.build();

またはそれを使用するつもりです。そして、あなたはすでにあなたのために構築されており、使用する準備ができていますが、変更することはできません。

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

これは使用する準備ができていますが、変更する場合は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

これを変更するたびに、buildUpon()および最後にbuild()を実行する必要があります。

したがって、Uri.BuilderBuilderを格納するBuilderタイプです。 Uriは、既に構築されているURIを格納するBuilt型です。

新しいUri.Builder(); Builderを再起動します。 Uri.parse( "ここにURIが入ります")Builtを返します。

また、build()を使用して、それをBuilderからBuiltに変更できます。 buildUpon()BuiltからBuilderに変更できます。これがあなたができることです

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

そしてまた反対:-

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

私の答えが役に立てば幸い:) <3


6

second Answer私の例では、同じ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);

ビルドが完了したら、次のURLようにします

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

接続を開く

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

simpleたとえば、リンクが場所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());MalformedURLExceptionのtry catchブロックでラップする必要があります
Ali Kazi

2

を使用appendEncodePath()すると、複数の行を節約できます。appendPath()次のコードスニペットは、この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

ベストアンサー:https : //stackoverflow.com/a/19168199/413127

の例

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

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

Kotlinバージョンを追加していただきありがとうございます:)
M Mansour

0

ラムダ式でそれを行うことができます。

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

そのようなパラメーターを作成できます。

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

ところでのような問題が発生する場合は“lambda expressions not supported at this language level”、このURLを確認してください。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.