Retrofit to consume APIs - android

I just started using Retrofit to consume APIs. I am able to update a User's profile successfully but I can't pass in the information to a User Object:
Interface RetrofitService:
public interface RetrofitService {
#FormUrlEncoded
#POST("/profile/update")
public void updateUser(
#Field("user_id") String userId,
#Field("user_token") String userToken,
#Field("first_name") String firstName,
#Field("last_name") String lastName,
Callback<JSONObject> callback);
}
Activity ProfileUpdate:
updateProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Build RestAdapter
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://xxx.xxx.xxx.xxx/")
.build();
//Create API service
RetrofitService service = restAdapter.create(RetrofitService.class);
//Invoke method
service.updateUser(
user.getUserId(),
user.getUserToken(),
mFirstName.getText().toString(),
mLastName.getText().toString(),
new Callback<JSONObject>() {
#Override
// user remains null!
public void success(JSONObject jsonObject, Response response) {
Toast.makeText(ProfileMe.this, "Profile Updated", Toast.LENGTH_SHORT).show();
Log.d("succes", "Success!");
}
#Override
public void failure(RetrofitError error) {
Log.d("failure", "Failed");
}
});
}
});
The above code works and the user's profile is updated. However the JSONObject in the onSuccess remains null.
I've been using Gson until now and I would do something like this:
//update user with new information
User user = gson.fromJson(responseData,User.class);
How do I do this with Retrofit?
EDIT
Response from the server returns a JSONObject. I changed the code above to satisfy those requirements but I am still returned a null JSONObject

Change to this:
public interface RetrofitService {
#FormUrlEncoded
#POST("/profile/update")
public void updateUser(
#Field("user_id") String userId,
#Field("user_token") String userToken,
#Field("first_name") String firstName,
#Field("last_name") String lastName,
Callback<User> callback);
}
You need to set in the callback what you are expecting to receive in the response. If the WS returns a User object you need to set that in the callback

Make sure that your rest has a Object as return (Json formatter).
You need change your code to this:
public interface RetrofitService {
#FormUrlEncoded
#POST("/profile/update")
public void updateUser(
#Field("user_id") String userId,
#Field("user_token") String userToken,
#Field("first_name") String firstName,
#Field("last_name") String lastName,
Callback<User> callback);
}
Retrofit uses Gson by default to convert HTTP bodies to and from JSON.
If you want to specify behavior that is different from Gson's defaults
(e.g. naming policies, date formats, custom types), provide a new Gson
instance with your desired behavior when building a RestAdapter. Refer
to the Gson documentation for more details on customization.
Edited
If your server returns something like this:
{
"user_id": "21q3123"
"user_token":"asd2334rter"
"first_name" : "User Test"
"last_name" : "user last name"
}
On your Android client you need to have something like this also
public class User {
String user_id;
String user_token;
String first_name;
String last_name;
//Getter and Setters
}
Retrofit by default use Gson to parser all requests.
See here a good example of Paser.com and Retrofit:
Android-Retrofit-Example

Related

Parse nested json using retrofit in Android

I am getting a Null Pointer Exception. I want to retrieve a random quote from this Quotes Api - https://quotes.rest/ to display in my android application. Where am I going wrong?
(I apologise if I had not asked the question properly or violated any rules by posting a question. This is my first time asking a question)
I have created necessary POJOs and tried retrieving the quote in the MainActivity.
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<Example> call = service.getRandomQuote();
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
String quote = response.body().getContents().getQuotes().get(0).getQuote();
Log.d(TAG, "onResponse: ************" + quote);
}
GetDataService
public interface GetDataService {
#GET("/quote/random")
Call<Example> getRandomQuote();
}
POJO- Quote
public class Quote {
#SerializedName("quote")
private String quote;
public Quote(String quote) {
this.quote = quote;
}
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = quote;
}
}
POJO- Contents
public class Contents {
#SerializedName("quotes")
#Expose
private List<Quote> quotes;
public List<Quote> getQuotes() {
return quotes;
}
public void setQuotes(List<Quote> quotes) {
this.quotes = quotes;
}
}
POJO- Example
public class Example {
#SerializedName("contents")
#Expose
private Contents contents;
public Contents getContents() {
return contents;
}
public void setContents(Contents contents) {
this.contents = contents;
}
}
RetrofitClientInstance class
public class RetrofitClientInstance {
private static Retrofit retrofit = null;
private static final String BASE_URL = "https://quotes.rest";
public static Retrofit getRetrofitInstance(){
if(retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
I expect the output to be a random quote from this Quotes Api (https://quotes.rest/) but I am getting a Null Pointer Exception. Following is the error-
java.lang.NullPointerException: Attempt to invoke virtual method 'com.platinumstudio.contactsdemo7.network.Contents com.platinumstudio.contactsdemo7.Example.getContents()' on a null object reference
at com.platinumstudio.contactsdemo7.MainActivity$3.onResponse(MainActivity.java)
The API that you're using here is this. As the API documentation says, an API key is required to fetch data. Since you didn't add an API key in your codes, it's should return an unsuccessful response with the HTTP Status Code of 401.
And it's always the best practice to check if the response is successful before proceeding to execute operations on received data to avoid crash issues in the app. Always keep this code snippet when you're fetching data from an API:
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if(response.isSuccessful && response.body() != null){
//Get contents & quote
}
else {
//Check response code & show the relevant error message through Toast or Dialog
}
}
#Override
public void onFailure(Call call, Throwable t) {
//Show a failed message to the user
}
}
I believe that you need to add Api key to your request, otherwise you'll not be allowed to access the data. Hence, your response's body is null, which causes the crash. As it says on the website:
For using the private end points and subscribing to the API please visit https://theysaidso.com/api.
https://theysaidso.com/api/
From the API website you will find the link to access the ramdom quote
here is the link:
http://quotes.rest/quote/random.json?api_key=
without the key you will get Unauthorized access
This API requires Authorization key to access the data. Hence, modify your interface GetDataService like below :
public interface GetDataService {
#GET("/quote/random/")
Call<Example> getRandomQuote(#HeaderMap Map<String, String> headerMap);
}
//HeaderMap will have authorization key and its value as <Key,Value> pair.

How to pass Parameter In retrofit

Hear is my API:
http://v2sgroups.in/Erp_V2s_Groups/AndroidPanel/OTPVerification/099567.
I try to call Api through retrofit framework , how can I pass parameter in retrofit like above link. 099657 is the passing parameter.
#GET("/AndroidPanel/OTPVerification/")
void otp(#Field("otp") String otp,
Callback<OTP> callback);
how to pass 099567 in using interface?
Its a path, you can do:
#GET("/AndroidPanel/OTPVerification/{otp}")
void otp(#Path("otp") String otp,
Callback<OTP> callback);
You can pass parameter by #QueryMap
Retrofit uses annotations to translate defined keys and values into appropriate format. Using the #Query("key") String value annotation will add a query parameter with name key and the respective string value to the request url .
public interface API{
#POST("media-details")
retrofit2.Call<MediaDetails>getMediaList(#QueryMap Map<String, String> param);
}
private void getData() {
Map<String, String> data = new HashMap<>();
data.put("id", "12345");
data.put("end_cursor", "00000");
Call<MediaDetails> mediaDetails = ServiceAPI.getService().getMediaList(data);
mediaDetails.enqueue(new Callback<MediaDetails>() {
#Override
public void onResponse(Call<MediaDetails> call, Response<MediaDetails> response) {
}
#Override
public void onFailure(Call<MediaDetails> call, Throwable t) {
System.out.println("Failed");
}
});
}

Retrofit in android?

I'm new to Retrofit. How can I send param and get Json from bellow url ?
http://xxx:8087/courier.svc/login?username=jim&password=123456
I need to a link for tutorial .
This code is in my MainActivity :
private void loadJSON(String username, String password) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.8.11:8087/sample.svc/")
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface_Login request = retrofit.create(RequestInterface_Login.class);
Call<JSONResponseLogin> call = request.getJSON(username, password);
call.enqueue(new Callback<JSONResponseLogin>() {
#Override
public void onResponse(Call<JSONResponseLogin> call, Response<JSONResponseLogin> response) {
JSONResponseLogin jsonResponse = response.body();
data = new ArrayList<>(Arrays.asList(jsonResponse.getLogin()));
}
#Override
public void onFailure(Call<JSONResponseLogin> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
My ModelLogin :
public class ModelLogin {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
My RequestInterface_Login :
public interface RequestInterface_Login {
#GET("/login/{username}/{password}")
Call<JSONResponseLogin> getJSON(#Path("username") String username, #Path("password") String password);
}
My JSONResponseLogin :
public class JSONResponseLogin {
private ModelLogin[] login;
public ModelLogin[] getLogin() {
return login;
}
}
But get me NullPointerException!
I get json from service same bellow :
{"Key":null,"Response":1}
Before you get call the retrofit you can just print the URL and then you can load URL in browser and see what response is coming you can add log by bellow line before call.enqueue(new Callback<JSONResponseLogin>()
Log.e(TAG, "API URL: " + call.request().url());
Check your response
And let me know I will help you ... coz i am using retrofit in my 3 projects
Do like this ...in interface
#GET("/courier.svc/login?)
Call<JSONResponseLogin> getJSON(#Query("username") String username,
#Query("password") String password);
and remove it from base .baseUrl("http://192.168.8.11:8087")
I am writing this post on 'Retrofit in android' using our latest Retrofit library, This plugin can be be used to Integrate Retrofit to your project.
Before using reftrofit, we just need to follow some steps to add QAssist Plugins in Android studio which will reduce your efforts of Webservices integration.
1.Add (QAssist - Android Studio Plugin) Android plugin in your Android studio. ( https://github.com/sakkeerhussain/QAssist ).:-
2.When we done with the plugin then we need to restart our Android studio.
3.Check your Android studio Menubar You can find "QAssist".
4.Click on that and Start with Retrofit Integrate.
5.Now we need :
- BaseUrl of Web Api's
- All Api's en points.
- Sample request and Response of All request.
- After completing these steps your reftrofit(QAssist/retrofit package is genrated inside Project).
6.You can find A Class and One Interface inside that Package.
7.The interface contain all the endpoints detail and Class will cotain the Retrofit connection details.
8.We just need to add a small code to access and Api and Parse that Api' response to Data model.
9.Use this sample function to call Api.
private void demoRetroFitCall() {
APIService apiService = RetrofitManager.getInstance(this);
//APIService apiService = RetroFitApiClient.getClient().create(APIService.class);
Call<ModelData> call = apiService.TestGet();
call.enqueue(new Callback<ModelData>() {
#Override
public void onResponse(Call<ModelData> call, Response<ModelData> response) {
Log.d("TAG", "Data recived in response.body");
}
#Override
public void onFailure(Call<ModelData> call, Throwable t) {
Log.e("TAG", t.toString());
}
});
}
56 - voda

retrofit get request with dynamic path

I have two APIs -
One to search for a phone number (let's say http://example.com/api/?phone=1234567890) which returns the id of the person associated with that phone number
And another (http://example.com/api/con/id/) to fetch for contact details.
Basically, in the second call, I have to include the id that is returned in the first call.
My question is how do I do this?
I've come till here in my code, but I couldn't find anything beyond this for my situation.
public interface RequestInterface {
#GET("/con/")
Call<JSONResponse> getJSON();
}
Since there is a change in dynamic path so if you are trying to call it from local server you need to create .htaccess file with following rules:
# Turn rewrite engine on
Options +FollowSymlinks
RewriteEngine on
# map neat URL to internal URL
RewriteRule ^api/con/([0-9]+)/?$ RestController.php?phone=single&id=$1 [NC,L,QSA]
RewriteCond %{QUERY_STRING} (?:^|&)number=(\d+)$
RewriteRule ^api/?$ RestController.php?phone=all&no=%1 [NC,L]
This will redirect your server based on the query parameters and URL.
public interface RequestInterface
{
BASE_URL = "http://example.com"
#GET("/api")
Call<YourFetchResponse> getPhoneDetails(#Query("api_key") String apiKey,#Query("phone") String phone);
#GET("/api/con/{id}")
Call<YourIdResponse> getIdDetails(#Query("api_key") String apiKey,#Path("id") String id);
}
MainActivity.java
Call<YourFetchResponse> call = RequestInterface.getPhoneDetails(API_KEY,PHONE);
call.enqueue(new Callback<YourFetchResponse>()
{
#Override
public void onResponse(Call<YourFetchResponse> call, Response<YourFetchResponse> response)
{
Call<YourIdResponse> call1 = RequestInterface.getIdDetails(API_KEY, response.body().getId);
call1.enqueue(new Callback<YourIdResponse>()
{
#Override
public void onResponse(Call<YourIdResponse> call, Response<YourIdResponse> response)
{....}
#Override
public void onFailure(Call<YourFetchResponse> call, Throwable t)
{....}
}
#Override
public void onFailure(Call<YourFetchResponse> call, Throwable t)
{....}
});
You need to use #Path annotation.
public interface RequestInterface {
BASE_URL = "http://example.com/api/";
#GET("con/{id}")
Call<YourFetchResponse> contactFetch(#Path("id") String id);
#GET("")
Call<YourIdResponse> contactId(#Query("phone") String phone);
}
Good luck there.
public interface RequestInterface {
#GET("serviceURL")
Call<JSONResponse> getPhoneDetails(#Query("api_key") String apiKey);
#GET("serviceURL")
Call<JSONResponse> getIdDetails(#Query("api_key") String apiKey);
}
onResponse of First service call second service.

Call webservice using Retrofit return invalid webservice result

I am using retrofit to retrieve login JSON result from server for that i need to post user name and password. I have tried this code but i get response saying invalid Web Service. but i get correct response using Rest.
My code is something like this,
MainActivity.java
String url = "http://***.***.in/***/******/*********/UserService.php?request=Verify_User_Credential";
//making object of RestAdapter
RestAdapter adapter = new RestAdapter.Builder().setEndpoint(url).build();
//Creating Rest Services
RestInterface restInterface = adapter.create(RestInterface.class);
//Calling method to get login report
restInterface.getLoginReport(username, password, new Callback<Model>()
{
#Override
public void success(final Model model, Response response) {
if (RetailConnectUtils.isSuccess(model.getStatus())) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// retrieve status and message from model and display
}
});
}
});
RestInterface::
#FormUrlEncoded
#POST("/GetData")
void getLoginReport(#Field("username")String uname,#Field("password")String password,Callback<Model> cb);
and POJO class model containing json converted values It contain method getStatus and getMessage...
Here what should i mention in #POST("******").. is that webservice method or default retrofit method?

Categories

Resources