Utilisez le générateur d'URI dans Android ou créez une URL avec des variables

202

Je développe une application Android. J'ai besoin de créer un URI pour mon application pour faire une demande d'API. À moins qu'il n'y ait une autre façon de mettre une variable dans un URI, c'est la manière la plus simple que j'ai trouvée. J'ai trouvé que vous devez utiliser Uri.Builder, mais je ne sais pas trop comment. Mon URL est:

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

Mon schéma est http, l'autorité est lapi.transitchicago.com, le chemin est /api/1.0, le ou les segments de chemin sont ttarrivals.aspxet la chaîne de requête est key=[redacted]&mapid=value.

Mon code est ci-dessous:

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

Je comprends que je peux le faire URI.add, mais comment l'intégrer dans le Uri.Builder? Dois-je tout ajouter URI.add(scheme), URI.add(authority)etc.? Ou n'est-ce pas la façon de procéder? De plus, existe-t-il un autre moyen plus simple d'ajouter une variable à un URI / URL?

hichris123
la source

Réponses:

426

Disons que je veux créer l'URL suivante:

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

Pour construire cela avec le Uri.Builderje ferais ce qui suit.

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
la source
1
Avec mon segment de chemin, serait-ce un chemin? Ou serait-ce une requête?
hichris123
S'il s'agit d'un chemin, ce serait appendPath()pour la méthode. S'il s'agit d'une chaîne de requête (après le?), Utilisez appendQueryParameter(). Jetez un œil à l'URL que j'ai dans l'exemple et à ce que je fais avec chaque segment. J'ai également ajouté toString()à l' build()appel pour récupérer le type approprié.
David
1
C'est avant le point d'interrogation, mais il n'a pas de / après. C'est ttarrivals.aspx sur ma question ci-dessus. Ce serait donc un chemin?
hichris123
Correct. Il se trouve que c'est la fin du chemin. Techniquement, vous pouvez mettre un "/" à la fin si vous le souhaitez et ce serait valide. mysite.com/path est le même que mysite.com/path
David
1
Réponse parfaite! Cela aurait dû déjà figurer dans la documentation de l'API.
robinmitra
259

Il y a une autre façon d'utiliser Uriet nous pouvons atteindre le même objectif

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

Pour construire l'Uri, vous pouvez utiliser ceci:

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

Vous pouvez déclarer tout cela de la manière ci-dessus ou même à l'intérieur du Uri.parse()etappendQueryParameter()

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

Enfin

URL url = new URL(builtUri.toString());
Amit Tripathi
la source
14
Vous méritez plus de votes! Pour moi, le cas d'utilisation de base est lorsque vous avez une URL de chaîne déjà définie et que vous souhaitez ajouter / ajouter des paramètres!
lorenzo-s
1
Je cherchais une solution pour le soleil (cette chaîne exacte) mais la question la plus votée fournit une solution beaucoup plus robuste.
Nahum
1
Merci pour l'indice Uri.buildUpon ()! M'a sauvé quelques maux de tête.
chrjs
Je ne savais pas dans quel ordre les URL sont faites, car bien sûr, ses seules variables, pas l'URL complète, que nous devons faire
blackHawk
Que faire si je n'ai pas l'URL de base mais l'URL complète à la place? En utilisant Parse + BuildUpon + AppendQueryParam + Build, j'obtiens une URL non valide ([domaine] [requêteParams] [chemin] au lieu de [domaine] [chemin] [requêteParams])
Giuseppe Giacoppo
20

Excellente réponse d'en haut transformée en une simple méthode d'utilité.

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
la source
Pas besoin de convertir du contenu UTF8?
Webserveis
15

voici un bon moyen de l'expliquer:

il existe deux formes d'URI

1 - Builder (prêt à être modifié , pas prêt à être utilisé )

2 - Construit ( pas prêt à être modifié , prêt à être utilisé )

Vous pouvez créer un constructeur en

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

ça va retourner un Builder prêt à être modifié comme ceci: -

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

mais pour l'utiliser, vous devez d'abord le construire

retrun builder.build();

ou comme tu vas l'utiliser. et puis vous avez construit qui est déjà construit pour vous, prêt à l'emploi mais ne peut pas être modifié.

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

ceci est prêt à l'emploi mais si vous voulez le modifier, vous devez 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

maintenant, chaque fois que vous voulez le modifier, vous devez buildUpon () et à la fin build () .

si Uri.Builder est un constructeur de type qui stockent un constructeur en elle. Uri est un type Built qui y stocke un URI déjà construit.

nouveau Uri.Builder (); renvoie un constructeur . Uri.parse ("votre URI va ici") renvoie un Built .

et avec build (), vous pouvez le faire passer de Builder à Built . buildUpon (), vous pouvez le faire passer de Built à Builder . Voici ce que vous pouvez faire

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

et aussi le contraire: -

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

j'espère que ma réponse a aidé :) <3

Mina Shaker
la source
6

pour l'exemple dans le second Answerj'ai utilisé cette technique pour la même 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);

puis après avoir terminé la construction, obtenez-le URLcomme ceci

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

et ouvrir une connexion

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

et si le lien est simplecomme l'emplacement uri, par exemple

geo:0,0?q=29203

Uri geoLocation = Uri.parse("geo:0,0?").buildUpon()
            .appendQueryParameter("q",29203).build();
Basheer AL-MOMANI
la source
2
URL url = new URL(builder.build().toString());doit être enveloppé par un bloc try catch pour MalformedURLException
Ali Kazi
2

L'utilisation appendEncodePath()pourrait vous faire économiser plusieurs lignes appendPath(), l'extrait de code suivant crée cette 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
la source
2

Meilleure réponse: https://stackoverflow.com/a/19168199/413127

Exemple pour

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

Maintenant avec 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
la source
Merci d'avoir ajouté la version Kotlin :)
M Mansour
0

Vous pouvez le faire avec des expressions 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();
    }

et vous pouvez créer des paramètres comme ça;

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

Btw. Si vous rencontrez un problème comme celui-ci “lambda expressions not supported at this language level”, veuillez vérifier cette URL;

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

yusuf
la source