Retrofit - Pass parameter in GET request with "/" form - android

This is the API I want to get: http://itunes.apple.com/us/rss/topsongs/limit=20/genre=29/explicit=true/json
How can I replace "29" by another number programmatically?
I have read many docs, but all of them have the same form with "?". Ex: https://api.example.com/tasks?id=123. I cannot apply their solution to my problem.
Thanks for your help.

Try this
#GET("users/{user}/repos")
Call<Response> listRepos(#Path("user") String user)

Try with
int your_number = 20;
String url = "http://itunes.apple.com/us/rss/topsongs/limit=20/genre=29/explicit=true/json;"
url = url.replace("genre=29", "genre"+your_number);
and now use url for requesting.

Related

Retrofit request url prevent urlencode android

I have a retrofit request
#GET("{link}")
suspend fun getFilePart(#Path(value = "link") link: String): Deferred<NetworkResponse<ResponseBody, NetworkError>>
and when i call it i pass a 'link'
val base = if (BuildConfig.DEBUG) BuildConfig.TRANSFER_URL_DEBUG else BuildConfig.TRANSFER_URL
apiManager.appApiService(base).getFilePart(it.link)
Lets say the link is something like "https://storage_dev.example.com/10002/6d197e1e57e37070760c4ae28bf1..." but in the Logcat i see that some characters get urlEncoded.
For example
the following Url
https://storage_dev.example.com/10002/6d197e1e57e37070760c4ae28bf18d813abd35a372b6a1f462e4cef21e505860.1&Somethingelse
turns to
https://storage_dev.example.com/10002/6d197e1e57e37070760c4ae28bf18d813abd35a372b6a1f462e4cef21e505860.1%3FSomethingelse
As i can see the link is a String that has many characters inside that get encoded like "&" has turned to "%3F"
How can i prevent this?
You can add encoded = true to your request param to tell retrofit to not encode it again:
/**
* Specifies whether the parameter {#linkplain #value() name} and value are already URL encoded.
*/
boolean encoded() default false;
Example:
#Path(value = "link", encoded = true)
If your link includes the baseurl part you should use #Url to avoid that problem
#GET
suspend fun getFilePart(#Url link: String): Deferred<NetworkResponse<ResponseBody, NetworkError>>
I think I'm late but however this is how I solved it ..
my issue was the url to containes " so on request url it gets encoded then looks like this domain.com/api/%22SOME_URL_%22
simply just add interceptor to catch the request and decode it.
if(it.request().url().toString().contains("api/MY_SUB_DOMAIN")){
val newUrl = java.net.URLDecoder.decode( it.request().url().toString(),
StandardCharsets.UTF_8.name()) // <--- This is your main solution (decode)
.replace("\"", "") // <---- I had to do this to remove parenthasis "
requestBuilder.url(newUrl) // <--- DONT FORGET TO ASSAIGN THE NEW URL
}

Android Retrofit: URL with braces ' { } ' causing errors

I am trying to fetch data from the following api:
https://site/api/requestpost/gethttp?dbName=ERP&PN=Mobile_CustomerList_P&JSONUser={"mb_code":"11111","pwd":"2222","id":"0000"}&JSONData={}
My code:
#GET(baseUrl+"gethttp?dbName=ERP&PN=Mobile_CustomerList_P&JSONUser={"+ "\"mb_code\":\"{key}\",\"pwd\":\"sj12\",\"id\":\"0000\"}&JSONData={{data}}")
Call<ResponseBody> downloadData(#Path(value = "key") String code, #Path("data")String data);
where
baseURL = "https://site/api/requestpost/";
key = "1111";
data = "";
With this code I am getting an error which says
...{{data}}"must not have replace block. For dynamic query parameters use #Query
Since this api has '{ }' in it, it's getting very hard to put it in retrofit.
I guess this error is because of the braces but they are a part of the api.
Retrofit expects you to build your service interface something like this:
#GET(baseUrl+"gethttp")
Call<ResponseBody> downloadData(
#Query("dbName") String dbName,
#Query("PN") String pn,
#Query("JSONUser") String jsonUser,
#Query("JSONData") String jsonData
);

Send a name/value pair as object in Multipart using Retrofit

In my code I have to make a MultipartForm-Data PUT request to update an object in the server, it ought to be Multipart as it is possible the user will send an image together with the data.
In order to do that, I am currently using Retrofit since it's a library I'm decently used to and it's working to send images to the server.
However, things have changed server-side and now one of the parameters that must be sent is:
{"step":
{"type":"begin"}
}
However that's been proving to be surprisingly hard to do.
Things I have tried include passing it as a MultipartTypedOutput, a hand-typed String and a JSONObject converted to String, all of which gave me:
retrofit.RetrofitError: 400 Bad Request
The URL being used is correct, I've double checked with the person who maintains the server and it is reaching the server, but with an incorrect "step" object.
I've also tried passing it as NameValuePair, Map and HashMap, all of which gave me:
retrofit.RetrofitError: Part body must not be null.
#FieldPart which looks to be perfect for this isn't compatible with Multipart, so is there a way to do this with Retrofit at all?
My current PUT method is as such:
#Headers({
"Connection: Keep-Alive",
"Accept-Language: en-US"
})
#Multipart
#PUT("/0.1/user/{id}")
String updateUser(#Path("id") String userId, #Part("step") Map<String,String> type);
Where the Map type has been changed to all the types I mentioned before.
You are actually doing it the correct way,just need some quick fix. I have two suggestions for you,
1. You can create a innerclass like this
public class Example {
#SerializedName("type")
#Expose
private String type;
/**
*
* #return
* The type
*/
public String getType() {
return type;
}
/**
*
* #param type
* The type
*/
public void setType(String type) {
this.type = type;
}
}
In this case, your api will look like
#Multipart
#PUT("/0.1/user/{id}")
String updateUser(#Path("id") String userId, #Part("step") Example exp);
or, you can use the JsonObject, this is not the Apache JSONObject that you have already used. Its the google gson object which comes under package of com.google.gson. Here you need to do the following,
JsonObject settingObject = new JsonObject();
settingObject.addProperty("type", "begin");
In this case, it will be,
String updateUser(#Path("id") String userId, #Part("step") JsonObject obj);
This is all you need, btw you can also set the header for once and all, why bother defining it over an api ?
I still don't understand what the issue is, as the "Part body must not be null" occurred even when trying out what Ankush mentioned.
Either way, I spoke to a few friends and a few contact expansions later, I got the following solution:
#Headers({
"Connection: Keep-Alive",
"Accept-Language: en-US"
})
#Multipart
#PUT("/0.1/user/{id}")
String updateUser(#Path("id") String userId, #Part("step[type]") String type);
As far as I could find, this isn't mentioned anywhere in retrofit's documentation, but it does work.

Retrofit2 Static encoded form data?

I have a new Android project I am working on, and Retrofit2 is working well for me. However, I have one url that I need to hit, with one of two strings, on top of the data I send.
Right now it looks like this:
#FormUrlEncoded
#POST("token")
Call<AccessResponse> requestAccess(#Field("grant_type") String type, #Field("code") String authCode, #Field("client_id") String ApiKey);
the grant type is only one of two things, and I would like to abstract it away, into static urls, like this:
#FormUrlEncoded
#POST("token")
#Field("grant_type","type1")
Call<AccessResponse> requestAccess( #Field("code") String authCode, #Field("client_id") String ApiKey);
#FormUrlEncoded
#POST("token")
#Field("grant_type","type2")
Call<AccessResponse> refreshAccess( #Field("code") String authCode, #Field("client_id") String ApiKey);
Is there a way to accomplish this? my 2 days of google-fu haven't worked for me, nor has browsing the API docs and code. I just don't want to have to keep track of the correct string in the various places in my code.
Turns out the answer is "You can't right now".
There is an open issue on Github for the feature request
There is an alternative approach, a FieldMap object with a method example as mentioned in this SO post, but it is not exactly what I was looking for, and overkill for just one field.
Could the Retrofit RequestInterceptor do the job ?
It can inject parameters into each request... so from there you could maybe write a method that injects the right parameter depending on what you're trying to do...
RequestInterceptor requestInterceptor = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addQueryParam("grant_type", getGrantType());
}
};
private String getGrantType()
{
// do your stuff and :
return "type1"; // or "type2"
}

Converting & to & in android?

I have a URL string in the following format.
http://myserver.com/_layouts/feed.aspx?xsl=4&web=%2F&page=dda3fd10-c776-4d69-8c55-2f1c74b343e2&wp=476f174a-82df-4611-a3df-e13255d97533
I want to replace & with & in the above URL. My result should be:
http://myserver.com/_layouts/feed.aspx?xsl=4&web=%2F&page=dda3fd10-c776-4d69-8c55-2f1c74b343e2&wp=476f174a-82df-4611-a3df-e13255d97533
Can someone post me the code to get this done?
i changed the code like this. but not working
if (name.equalsIgnoreCase(LINK))
{
Log.v(TAG,"link link: "+property.getFirstChild().getNodeValue().replace("&","&"));
message.setLink(property.getFirstChild().getNodeValue().replace("&","&"));
}
Thanks
How about:
private String decode(String url)
{
return url.replace("&", "&");
}
Decode:
Html.fromHtml((String) htmlCode).toString();
Encode:
TextUtils.htmlEncode(url)
String.replace(target, replacement)

Categories

Resources