Consume Google Elevations Api from Android - android

I want to get the json file containing the elevation of a given latitude and longitude (and also providing the api key). I have been reading a lot and find out that Retrofit is the best option in Android, but I don't know how to specify the params.
public interface ServiceApi {
//url format
//"https://maps.googleapis.com/maps/api/elevation/json?locations="
// latitude+","+longitude+"&key="+key;
#GET("")
public void getJSON(Callback<List<JsonElevation>> jsonElevationCallback);
}

I don't have an Elevations API key to test this with but using Retrofit's documentation, something like this should work.
#GET("/maps/api/elevation/json")
public Call<List<JsonElevation>> getJSON(#Query("locations") String latAndLng,
#Query("key") String key);
Then to call it:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://maps.googleapis.com/")
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
ServiceApi serviceApi = retrofit.create(ServiceApi.class);
String latAndLng = String.format("%f,%f", latitude, longitude);
Call<List<JsonElevation>> elevations = serviceApi.getJSON(latAndLng, key);
elevations.enqueue(); // for asychronous response
//or
elevations.execute(); // for synchronous response

Related

Do I need to make new interfaces every time in Retrofit 2

I want to ask that do I need to create new Interfaces for every POST GET request I make which have different URL .
For ex
I made 1 interface for register and other for Login other for getting Friends. Cant I just make 1 general post and get method where I can send URL , params to send and record response?
No you don't need to create new interface or new client for each request!
Inside a interface you can create multiple method as you want and as your requirement.
For Login and fro Registration method name will be different, your parameter will not same. So you can create method as you need.
//When Base Url like "http://exmaple.com/"
#GET("Service/registration")
Call<RegResult> getRegistered(#Query("name") String name,
#Query("email") String email,
#Query("dob") String dob,
#Query("name") String name
);
#GET("Service/login")
Call<LoginResult> getLogin(#Query("username") String username,
#Query("pass") String pass
);
#GET("Service/profile")
Call<ProfileResult> getProfile(#Query("userid") String userid
);
You can also use same client because your base url is same.
If base url is diffrent you can also use same client like this..
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String base_url) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(base_url)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Now you can set different base url.
Creating object of interface...
String BASE_URL = "http://exmaple.com/";
ApiInterface apiService = ApiClient.getClient(BASE_URL).create(ApiInterface.class);
Calling method..
String user_id = "1";
Call< ProfileResult > call = apiService.getProfile(user_id);
Getting result
call.enqueue(new Callback< ProfileResult >() {
#Override
public void onResponse(Call< ProfileResult >call, Response< ProfileResult > response) {
Profile profile = response.body().getResults();
}
#Override
public void onFailure(Call< ProfileResult >call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
Hop you got your answer .... for farther query fill free to ask...

How to parse dynamic JSON with Retrofit?

I have dynamic JSON, here is example: http://pastebin.com/QMWRZTrD
How I can parse it with Retrofit?
I failed to generate POJO classes, since I have dynamic fields like "5411" and "5412".
EDIT:
I solved it by using Map, since first value is always integer, and second is list of objects.
#FormUrlEncoded
#POST("history.php")
Observable<Map<Integer, List<Vehicle>>> getHistory(#Field("uredjaji") String vehicleId, #Field("startDate") String startDATE, #Field("endDate")
you can use Map to serialize and deserialize it in case of Random keys.
Observable<Map<Integer, List<YourObject>>>
You can get retrofit api call to return String in your RestApi Interface like
Call<String> method(#Path(..)...);
And for that to work you would need to add the scalars converter factory to where you create your Retrofit object.
First you would need to import it:
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
And then add it:
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://your.base.url/")
.build();
And then in onResponse
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
Type mapType = new TypeToken<Map<String,List<SomeClass>>() {}.getType(); // define generic type
Map<String,List<SomeClass>> result= gson.fromJson(response.body(), mapType);
} else {
}
}
Also,check out this site it has great tutorials on Retrofit.

Retrofit2 Specify root element and convert datatype

I've just started working with Retrofit2 and the API I'm consuming wraps all valid responses in a "response" object as shown below. I need to tell Retrofit to parse only the values within response without actually nesting them inside another object. For the login code, I'm also faced with the issue of getting a String which I want to convert to an actual time stamp.
This is a sample response from a login request:
{
"status":"success",
"response":{
"token":"test_token",
"expires":"1485217863"
}
}
In the above the only two actual values are:
token
expires
I'm hoping to end up with something like what is shown below.
public class Token {
#SerializedName("token")
String token;
#SerializedName("expires")
Timestamp expires;
public User(String token, String expires ) {
this.token
this.expires = //conversion code omitted.
}
}
You have a couple of options here. You can either use a custom serialiser/deserialiser, type adapters, or you can simply use pojos and unwrap the result yourself.
Let me start with the easiest solution I can think of. Picture you have these classes:
public class ResponseData<T> {
#SerializedName("status")
#Expose
String status;
#SerializedName("response")
#Expose
T response;
public T getResponse() {
return response;
}
// getters and setters and friends
}
public class Token {
#SerializedName("token")
#Expose
String token;
#SerializedName("expires")
#Expose
Timestamp expires;
public Token(String token, String expires) {
this.token = token;
this.expires = expires;
}
}
So one first thing to notice is the use of #Expose. This is a nice to have, but not extremely necessary. It helps you out when you have custom serialisers.
I assumed that you can have multiple api endpoints that return the same kind of body, where the json is:
{
"status":"success",
"response":{
// Can be anything
}
}
And as you can see the response can be anything.
You can then make your retrofit calls return ResponseData<Token> and in your callbacks you can check the value of status and see if you can do getResponse to unpack the result. The advantage of this approach is that you can reuse ResponseData fairly easily.
Another approach is to use custom serialisers or type adapters. This is in my opinion more laborious, but still a valid approach. I think the answer here is quite extensive and explains how you can do this to get the nested object inside response.
To prepare retrofit to use the type adapters, you'll need to inject a configured Gson instance into it. Here's how:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Token.class, new YourTypeAdapter())
.create();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
// ....
As you can see, we pass the created gson with your type adapter to the GsonConverterFactory used by retrofit. This prepares retrofit to serialise and deserialise Token objects using the given type adapter.
I think the main disadvantage with this approach is that if you want to write a generic deserialiser/serialiser/typeadapter it can become complicated quite fast (assuming you won't have only a Token object).

Dinamic headers in Retrofit (1-2) do not work

I'm trying to make authtoken GET request to my server.
I'm trying to do in like this:
public interface FixedRecApi {
public static final String ENDPOINT = "http://******.pythonanywhere.com/";
//#Headers("Authorization: Token ce7950e8d0c266986b7f972407db898810322***") this thing work well!!
#GET("/auth/me/")
Observable<User> me(#Header("Authorization: Token") String token); //this does not work at all!
Observable<User> me();
}
So as you see, the line with explicit header: #Headers - works perfect.
But when I try to pass it as a parameter - it says "no credentials provided".
My application onCreate:
#Override
public void onCreate() {
super.onCreate();
ActiveAndroid.initialize(this);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(FixedRecApi.ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(
GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.excludeFieldsWithoutExposeAnnotation()
.serializeNulls()
.create()))
.build();
service = retrofit.create(FixedRecApi.class);
}
Have no idea what is wrong with this thing. Interceptors don't work either...
I've found the solution. Headers consist of two parts:
header name: "Authrorization"
then colon
header value: "Token ce7950e8d0c266986b7f972407db898810322***"
So, Retrofit usage should be:
Observable<User> me(#Header("Authorization") String token);
and then for example in MainActivity:
RetrofitApi.me("Token " + "ce7950e8d0c266986b7f972407db898810322***");

Retrofit response not being entirely parsed

I have an Android application that uses a RestFUL web service as its backend. I already implemented Retrofit for sending registration data and it works.
Now I need to get a big load of objects, but it's not working yet. I noticed Gson only parses a few attributes (name, type, location), but most of them were not (specially id).
How does Gson actually parse it? Do I actually have to implement it? From what I thought I just needed the name of the attributes to match and it would do all the work for me.
This is how I am building my Gson and RestAdapter:
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(PACURL.getHost())
// .setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new GsonConverter(gson))
.build();
My request definition:
#POST("/pois/{category}")
void getPois(#Path("category") String category,
#Query("lat") Double lat,
#Query("long") Double lon,
Callback<WrapperPois> callback);
And the actual call:
NetworkInterface nt = restAdapter.create(NetworkInterface.class);
nt.getPois(category,
location.getLatitude(),
location.getLongitude(), callback);
I used Retrofit expecting to ease my work, so please let me know if I have to actually write the deserialization myself. Any comments on how Gson default converter works is very appreciated.
Thanks!
Edit:
My WrapperPois class:
public class WrapperPois {
public ArrayList<Poi> results;
static class MyResponse {
public ArrayList<Poi> array;
}
}
And the Poi contains:
protected String objectId;
protected String url;
protected String type;
...

Categories

Resources