I'm trying to get ِِOAuth token in android from my web api. I have tested the api in Postman and it's working perfect.
Screenshot for the successful call from Postman
now I need to call this Api from my android app using retrofit 2 to get the token, for that I tried to use the following interface but it's not working.
#FormUrlEncoded
#POST("/Token")
public Call<String> Token(#Field("grant_type") String grant_type, #Field("username") String username, #Field("password") String password);
How can I get this done?
In my case I using this below way to call Web Api in Android Application.
Note : I am using OkHttp library.
Create Token class
public class Token {
public String access_token;
public String token_type;
public int expires_in;
public Token(){
}
}
Now add OkHttp library jar to your Project.
for more detail visit this :
http://square.github.io/okhttp/
Now to get OAuth Token call this way
OkHttpClient client = new OkHttpClient();
Request.Builder builder = new Request.Builder();
builder.url(write your url here);
builder.addHeader("Content-Type", "application/x-www-form-urlencoded");
builder.addHeader("Accept", "application/json");
FormEncodingBuilder parameters = new FormEncodingBuilder();
parameters.add("grant_type", "password");
parameters.add("username", edituser);
parameters.add("password", editpassword);
builder.post(parameters.build());
try {
Response response = client.newCall(builder.build()).execute();
if (response.isSuccessful()) {
String json = response.body().string();
}
catch(Exception e){
// catch Exception here
}
finally in response you will get your Token.
Late but it might help someone
Interface class
#FormUrlEncoded
#POST("/Token")
void getTokenAccess(#Field("grant_type") String grantType, #Field("username") String username, #Field("password") String password, Callback<TokenResponse> callback);
TokenResponse class
public class TokenResponse {
private String access_token,token_type,expires_in,userName;
public String getAccess_token() {
return access_token;
}
public String getToken_type() {
return token_type;
}
public String getExpires_in() {
return expires_in;
}
public String getUserName() {
return userName;
}
}
I am using retrofit 1.9.0
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT_URL).setLogLevel(RestAdapter.LogLevel.FULL)
.build();
NetApi api = adapter.create(NetApi.class);
api.getTokenAccess("password", email, password, new Callback<TokenResponse>() {
#Override
public void success(TokenResponse tokenResponse, Response response) {
showProgress(false);
try{
MainActivity.tokenResponse = tokenResponse;
startActivity(new Intent(LoginActivity.this, MainActivity.class));
}catch (Exception e){
Toast.makeText(LoginActivity.this,"Unknown Error",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(LoginActivity.this,""+error.getMessage(),Toast.LENGTH_LONG).show();
showProgress(false);
}
});
Related
I am trying to use login api via retrofit. I need to send only mobile number. When i am using postman body it is getting an output. but when iam calling with android its getting an error json like below
{
"error": "Validation error",
"error_code": "001",
"Validation_errors": {
"mobile": "<p>The Mobile field is required.</p>"
}
}
HomeActivity.class
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Map<String,String> user = new HashMap<>();
user.put("mobile",username.getText().toString().trim());
Call<ResponseBody> mService = apiService.loginwithno(user);
Log.d("TAG", "response: " + mService.toString());
mService.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
String result = response.body().string();
JSONObject mJsonObject = new JSONObject(result);
Log.d("TAG", "response: " + mJsonObject.toString());
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
buttonVisible();
username.setError("Please try again");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
call.cancel();
buttonVisible();
Snackbar snackbar = Snackbar.make(buttonLogin,
"Please check your internet connection", Snackbar.LENGTH_LONG);
snackbar.show();
}
ApiClient
public class ApiClient {
public static final String BASE_URL = "http://nast.in/driverpool/api/index.php/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
ApiInterface
public interface ApiInterface {
#POST("account/login?")
Call<ResponseBody> loginwithno(#Body Map<String, String> mobile);
#POST("account/verifyotp")
Call<ResponseBody> verifyotp(#Body HashMap<String, String> mobile);//Param name: mobile, otp
#POST("account/resendotp")
Call<ResponseBody> resentotp(#Body HashMap<String, String> mobile);
}
Postman screenshot
First you don't need '?' in your api and i think you must send json in your #body so create class like this
public class SendLoginData{
#SerializedName("mobile")
public String mobile;
public SendLoginData(String mobile) {
this.mobile = mobile;
}
}
And use it in ApiInterface
#POST("account/login")
Call<ResponseBody> loginwithno(#Body SendLoginData post);
You need to make few changes in code.
Change your login api to receive json like this, include gson library if you have not added in project.
#POST("account/login?")
Call loginwithno(#Body Map mobile);
Create an ApiErrorResponse object to handle your api error. Add getter, setter and #SerializedName as required.
class ApiErrorResponse{
String error;
String error_code;
ValidationErrors Validation_errors;
}
class ValidationErrors{
String mobile;
}
on API error handle like this
if(!response.isSuccessful()){
Converter converter =
ApiClient.getClient().responseBodyConverter(ApiErrorResponse.class, new Annotation[0]);
ApiErrorResponse errors = null;
try {
errors = converter.convert(response.errorBody());
} catch (Exception e) {
}
if(errors!=null){
//Handle your API Error logic here
}
}
I just wanted to know that how could I convert this retrofit library response which is actually a JSON response to JSON object so I could use this in my android app to do something because I can not do anything with response in the buffered reader.
public void getMe(){
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ROOT_URL)
.build();
myApi api = adapter.create(myApi.class);
api.sendme(
userEmail,
rs,
Team1,
Team2,
new retrofit.Callback<retrofit.client.Response>() {
#Override
public void success(retrofit.client.Response result, retrofit.client.Response response) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
if (!output.equals("")) {
output = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void failure(RetrofitError error) {
// loading.dismiss();
Toast.makeText(Leaderboard.this, "", Toast.LENGTH_LONG).show();
}
}
);
}
here get me is sending post response to the server
public interface myApi {
#FormUrlEncoded
#POST("/myleaderboard.php")
void sendme(
#Field("userEmail") String userEmail,
#Field("rs") String rs,
#Field("team1") String team1,
#Field("team2") String team2,
Callback<Response> callback);
}
I m getting JSON response and I have to store that in my android code somehow whether that be using JSON object or anything else if possible.
please help me with this
Just change the myAPi code to
public interface myApi {
#FormUrlEncoded
#POST("/myleaderboard.php")
void sendme(
#Field("userEmail") String userEmail,
#Field("rs") String rs,
#Field("team1") String team1,
#Field("team2") String team2,
Callback<JsonObject> callback);
}
it will return JsonObject directly
Use GsonConverterFactory to convert incoming json into model/pojo class
implementation 'com.squareup.retrofit2:converter-gson:LATEST_VERSION'
Please go through following links
Retrofit Library Tutorial
Consuming-APIs-with-Retrofit
Use this link to convert your JSON into POJO with select options as selected in image below [http://www.jsonschema2pojo.org/
You will get a POJO class for your response like this
public class Result {
#SerializedName("id")
#Expose
private Integer id;
/**
*
* #return
* The id
*/
public Integer getId() {
return id;
}
/**
*
* #param id
* The id
*/
public void setId(Integer id) {
this.id = id;
}
then and use interface like this:
#FormUrlEncoded
#POST("/api/level")
Call<Result> checkLevel(#Field("id") int id);
add the dependencies
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.+'
and call like this:
Call<Result> call = api.checkLevel(1);
call.enqueue(new Callback<Result>() {
#Override
public void onResponse(Call<Result> call, Response<Result> response) {
response.body(); // have your all data
int id =response.body().getId();
String userName = response.body().getUsername();
String level = response.body().getLevel();
}
#Override
public void onFailure(Call<Result> call, Throwable t) {
}
});
to get the response in JSON don't use addConverterFactory(GsonConverterFactory.create()) from Retrofit.
Im using retrofit to send a a json object to the server, im trying to create a user, im sending this json object
{"apellido":"prueba","email":"prueba#hotmail.com","fechaDeNacimiento":"11/29/1998","formaDeRegistro":"Android","nombre":"prueba","password":"12345678","username":"prueba"}
In this example i create a invalid user , so the server response with a json object where code its the code error and message its the explication of the error
[{"code":"5","message":"The email is in use"}]
Interface
public interface UserClient {
#POST("usuarios")
Call<Usuarios> create(#Body Usuarios usuario);
}
Data model
import com.google.gson.annotations.SerializedName;
public class Usuarios {
#SerializedName("username")
String username;
#SerializedName("email")
String email;
#SerializedName("password")
String password;
#SerializedName("nombre")
String nombre;
#SerializedName("apellido")
String apellido;
#SerializedName("fechaDeNacimiento")
String fechaDeNacimiento;
#SerializedName("formaDeRegistro")
String formaDeRegistro;
String message;
public Usuarios(String email, String username, String password, String nombre, String apellido, String fechaDeNacimiento, String formaDeRegistro){
this.username=username;
this.email=email;
this.password=password;
this.nombre = nombre;
this.apellido= apellido;
this.fechaDeNacimiento = fechaDeNacimiento;
this.formaDeRegistro = formaDeRegistro;
}
public String getMessage(){
return message;
}
}
and Retrofit implement
OkHttpClient.Builder okhttpClientBuilder=new OkHttpClient.Builder();
HttpLoggingInterceptor loggin=new HttpLoggingInterceptor();
loggin.setLevel(HttpLoggingInterceptor.Level.BODY);
okhttpClientBuilder.addInterceptor(loggin);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://intense-lake-39874.herokuapp.com")
.addConverterFactory(GsonConverterFactory.create())
.client(okhttpClientBuilder.build());
Retrofit retrofit = builder.build();
UserClient service = retrofit.create(UserClient.class);
Call<Usuarios> call = service.create(usuario);
call.enqueue(new Callback<Usuarios>() {
#Override
public void onResponse(Call<Usuarios> call, Response<Usuarios> response) {
Toast.makeText(Main2Activity.this,"Usuario Registrado! "+response.body().getMessage,Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<Usuarios> call, Throwable t) {
Toast.makeText(Main2Activity.this,"Algo fallo..",Toast.LENGTH_SHORT).show();
}
});
}
So i can see the logcat response but in the body its appoint to null, how i can acces to the "message"?
This is the logcat
That error is because your response is not successful therefore you need to parse the error body, try with this code:
if (response.isSuccessful()) {
// Do your success stuff...
} else
{
try
{
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(getContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
Of course that you can use another parser like Gson .
I'm starting to work with Retrofit but I'm stuck on this simple step. I have a login form and I'm trying to authenticate with the server but I just can't send the request.
This is what I've tried:
My Retrofit client:
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
My login interface:
public interface Login {
#POST(LOGIN)
Call<String> loginWithCredentials(#Body LoginCredentials data);
}
The LoginCredentials class:
public class LoginCredentials {
private String name;
private String pass;
public LoginCredentials(String name, String pass) {
this.name = name;
this.pass = pass;
}
}
And the part where I call it:
#Override
public void onClick(View v) {
showProgress(true);
String username = userField.getText().toString();
String password = passField.getText().toString();
ApiController.Login loginClient = ApiController.createService(ApiController.Login.class);
Call<String> call =loginClient.loginWithCredentials(new LoginCredentials(username, password));
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
handleResponse(response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
showProgress(false);
Log.e(TAG, t.getLocalizedMessage());
}
});
}
And I keep getting the error Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $but I have no idea what it means.
I figured it out. It was easier than I thought. You can skip the parsing that Retrofit does by setting the response type of the method as ResponseBody. Them you just need to read the response and use the string() method that provides. That's it!
Example:
public interface Login {
#POST(LOGIN)
Call<ResponseBody> loginWithCredentials(#Body LoginCredentials data);
}
Then use like this:
String username = userField.getText().toString();
String password = passField.getText().toString();
ApiController.Login loginClient = ApiController.createService(ApiController.Login.class);
Call<ResponseBody> call = loginClient.loginWithCredentials(new LoginCredentials(username, password));
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
// get String from response
String stringResponse = response.body().string();
// Do whatever you want with the String
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// handle error
}
});
This error means that gson trying to parse string from server as JSON object and can't find the opening bracket.
I think you could return actual JSON from server like
{"api_token": "token"}
Also this bug could possibly be solved by importing latest GSON version mentioned here
So I am trying to use retrofit to get the access token from our OAuth secured backend.
Basically I need to covert the following cURL command into retrofit :
curl -X POST -d "grant_type=password&phone_number=123123123&password=12345" -u"Client_Id:Client_Secret" http://baseURL/o/token
Here is my service
public interface LoginService {
#POST("/o/token")
#FormUrlEncoded
Observable<LoginEntity> getAccessToken(#Field("grant_type") String grantType,
#Field("phone_number") String phoneNumber,
#Field("password") String password,
#Header("Authorization") String authorization);
}
Here is my service generator code:
public void login(final MySubscribe<LoginEntity> subscriber, String pn, String psw) {
mRetrofit = new Retrofit.Builder()
.baseUrl(MyFeeds.APP_BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
//encode pn
String real_pn = getRealPN(pn);
//encode the credential using base64
String credential = MyFeeds.CLIENT_ID+":"+MyFeeds.CLIENT_SECRET;
String auth = null;
try {
auth = "Basic " + getBase64String(credential);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
LoginService service = mRetrofit.create(LoginService.class);
Observable<LoginEntity> observable = service.getAccessToken("password", real_pn, psw, auth);
mSubscription = observable.subscribeOn(Schedulers.newThread())
.doOnSubscribe(new Action0() {
#Override
public void call() {
subscriber.onBegin();
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
However I keep getting http500 error.
I have read the following post but it doesn't help
CURL -u request with Retrofit
Can anyone help? Thanks