How to send 2 parameters in body with retrofit? - java

Good night everybody.
I need to do a POST request and I'm using Retrofit 2 to do this.
But the Api I'm consuming does not give me these parameters in the API response, just in the body.
Api Response
I already searched in some places but I did not find anything that could help me.
My interface Class
public interface LoginApi {
#POST("api/login")
Call<UserAccount> doLogin(#Body Login login);
}
My Model Class
public class Login {
public String user;
public String password;
}
My API response class
public class UserAccount {
#SerializedName("userId")
#Expose
private Integer userId;
#SerializedName("name")
#Expose
private String name;
#SerializedName("bankAccount")
#Expose
private String bankAccount;
#SerializedName("agency")
#Expose
private String agency;
#SerializedName("balance")
#Expose
private Double balance;
}
My call class
public class LoginPresenter {
private LoginView loginView;
private ServiceConfig serviceConfig;
public LoginPresenter() {
this.loginView = loginView;
if (this.serviceConfig == null) {
this.serviceConfig = new ServiceConfig();
}
}
public void doLogin(Login login) {
serviceConfig
.login()
.doLogin(login)
.enqueue(new Callback<UserAccount>() {
#Override
public void onResponse(Call<UserAccount> call, Response<UserAccount> response) {
UserAccount userAccount = response.body();
assert userAccount != null;
Log.e("Agency:",userAccount.getAgency());
Log.e("BankAccount:", userAccount.getBankAccount());
Log.e("Name:", userAccount.getName());
}
#Override
public void onFailure(Call<UserAccount> call, Throwable t) {
Log.d("Erro", t.getMessage());
}
});
}
}
My Activity
public class LoginActivity extends Activity implements LoginView {
private EditText edtUser, edtPassword;
private Button btnLogin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
init();
}
private void init() {
edtUser = findViewById(R.id.edt_user);
edtPassword = findViewById(R.id.edt_password);
btnLogin = findViewById(R.id.btn_login);
final LoginPresenter loginPresenter = new LoginPresenter();
final Login login = new Login();
login.user = edtUser.getText().toString();
login.password = edtPassword.getText().toString();
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loginPresenter.doLogin(login);
}
});
}
#Override
public void userAccount(List<UserAccount> userAccount) {
}
}
I hope I have made my problem clear and that someone who has been through it can help me.
Appreciate.

Pass #Body JsonObject body instead of #Body Login login
Here is full code:
Your interface will be:
public interface LoginApi {
#POST("api/login")
Call<UserAccount> doLogin(#Body JsonObject body);
}
How to Create JsonObject :
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("user", userValue);
jsonObject.addProperty("password", passwordValue);
Pass it from your activity to presenter.
Hope it will works for you.
Thank you.

Pass Like This:-
You Interface
public interface ApiInterface {
String URL_BASE = "Base Url";
#Headers("Content-Type: application/json")
#POST("login")
Call<User> getUser(#Body String body);
}
Activity
public class SampleActivity extends AppCompatActivity implements Callback<User> {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
// prepare call in Retrofit 2.0
try {
JSONObject paramObject = new JSONObject();
paramObject.put("email", "sample#gmail.com");
paramObject.put("pass", "4384984938943");
Call<User> userCall = apiInterface.getUser(paramObject.toString());
userCall.enqueue(this);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onResponse(Call<User> call, Response<User> response) {
}
#Override
public void onFailure(Call<User> call, Throwable t) {
}
}

Related

Get values From ViewModel MutableLiveData and display them on textfields

I am trying to get a hang of the Android Architecture Library and i have been trying to display texts from retrofit via a ViewModel using Mutable LiveData on my Main Activity but i cant seem to do it, i would really appreciate some assistance.
Here is my Model Class
public class User {
#SerializedName("name")
#Expose
private String name;
#SerializedName("email")
#Expose
private String email;
#SerializedName("phone")
#Expose
private String phone;
public User() {
}
public String getUserName() {
return name;
}
public void setUserName(String name) {
this.name = name;
}
public String getUserEmail() {
return email;
}
public void setUserEmail(String email) {
this.email = email;
}
public String getUserPhone() {
return phone;
}
public void setUserPhone(String phone) {
this.phone = phone;
}
}
My View model
public class UserViewModel extends AndroidViewModel {
private NodeAuthService api;
private SharedPreferences pref;
private static MutableLiveData<List<User>> userDetails = new
MutableLiveData<>();
private Call<List<User>> call;
public UserViewModel(#NonNull Application application) {
super(application);
api = AuthRetrofitClient.getInstance().create(NodeAuthService.class);
}
private String email = pref.getString("email", "");
public void loadUser(){
call = api.getUser(email);
call.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>>
response) {
List<User> users = response.body();
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Log.d("USER",t.getMessage());
}
});
}
public MutableLiveData<List<User>> getUserDetails(){
return userDetails;
}
}
Simplified version of my MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView navName = (TextView) findViewById(R.id.navigation_name);
TextView navEmail = (TextView) findViewById(R.id.navigation_email);
}
Kindly assist
In your viewModel
public void loadUser(){
call = api.getUser(email);
call.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>>
response) {
userDetails.postValue(response.body())
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Log.d("USER",t.getMessage());
}
});
}
And in your Activity observe the changes
yourVm.getUserDetails().observe(this, models -> {
if (models != null) {
for(int = 0; i<models.size();i++){
/*you will get your list here now iterate through list and get
your email_id here.*/
}
}
});
instead of this
List<User> users = response.body();
use this
userDetails.postValue(response.body())
also, remove static before livedata
inside activity oncreate() init your viewModel instance.
then viewModel.getUserDEtails().obsever(this, data-> // your stuff);

how to send a string between classes?

hello guys I would like to sending string between java class in android studio.
I have class CreateToken.java and MainActivity.java, how can I send String yourToken to MainActivity.java and how can i receive string yourToken in MainActivity.java, and the result of yourToken is com.example.user.application.CreateToken#yourToken but yourToken is not full token , its just 7 charecter.
this is one of my function in CreateToken.java :
public class CreateToken {
private ICreateToken listener;
public CreateToken(ICreateToken listener) {
this.listener = listener;
}
public Call<Token> api(final Context ctx){
ApiInterface api = ApiClient.getClient().create(ApiInterface.class);
String usernameApi = "web";
String passwordApi = "123";
Call<Token> getToken = api.postWebService(usernameApi,passwordApi);
getToken.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
String error = response.body().getError();
if (error.equals("false")){
Toast.makeText(ctx, response.body().getToken(),Toast.LENGTH_SHORT).show();
Log.d("Smart","Response : Token Show");
String yourToken = response.body().getToken();
listener.onTokenGenerated(yourToken);
}else {
Toast.makeText(ctx, response.body().getMessage(),Toast.LENGTH_SHORT).show();
Log.d("Smart","Response : Token NUll");
}
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
Log.d("Smart","Response : Token Null");
}
});
return getToken;
}
public interface ICreateToken {
void onTokenGenerated(String token);
}
}
and this is my MainActivity.java :
public class MainActivity extends AppCompatActivity implements CreateToken.ICreateToken {
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
CreateToken token = new CreateToken(MainActivity.this);
textView.setText(token.toString());
}
#Override
public void onTokenGenerated(String token) {
}
}
I think that you could use the AsyncTask class from Android framework:
https://developer.android.com/reference/android/os/AsyncTask
Then use the methods doInBackground to call the webservice and onPostExecute use the response from that call:
public ActivityExample extends AsyncTask <clazz1,clazz2,clazz3> {
doInBackGround(clazz1 clazz){
return result;
}
onPostExecute(clazz2 result){
}
}
create an interface ICreateToken within CreateToken class as below
public interface ICreateToken {
void onTokenGenerated(String token);
}
Also declare Interface field in CreateToken class
private ICreateToken listener;
and from your MainActivity pass context in CreateToken class like this
CreateToken token = new CreateToken(MainActivity.this);
then initialise the listener in CreateToken constructor
public CreateToken(ICreateToken listener) {
this.listener = listner;
}
finally from onResponse you can return token via
listener.onTokenGenerated(yourToken)
Last and most important
MainActivity extends AppCompatActivity implements ICreateToken
implement ICreateToken in MainActivity which will ask to implement onTokenGenerated in MainActivity there you'll receive your token.

Sending a token between classes

I would like to sending string between java class in android studio. I have class CreateToken.java and MainActivity.java, how can I send string yourToken to MainActivity.java and how can I receive string yourToken in MainActivity.java, and the result of yourToken is com.example.user.application.CreateToken#yourToken but yourToken is not full token, its just 7 charecter.
This is one of my function in CreateToken.java:
public class CreateToken {
private ICreateToken listener;
public CreateToken(ICreateToken listener) {
this.listener = listener;
}
public Call<Token> api(final Context ctx){
ApiInterface api = ApiClient.getClient().create(ApiInterface.class);
String usernameApi = "web";
String passwordApi = "123";
Call<Token> getToken = api.postWebService(usernameApi,passwordApi);
getToken.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
String error = response.body().getError();
if (error.equals("false")){
Toast.makeText(ctx, response.body().getToken(),Toast.LENGTH_SHORT).show();
Log.d("Smart","Response : Token Show");
String yourToken = response.body().getToken();
listener.onTokenGenerated(yourToken);
}else {
Toast.makeText(ctx, response.body().getMessage(),Toast.LENGTH_SHORT).show();
Log.d("Smart","Response : Token NUll");
}
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
Log.d("Smart","Response : Token Null");
}
});
return getToken;
}
public interface ICreateToken {
void onTokenGenerated(String token);
}
}
And this is my MainActivity.java:
public class MainActivity extends AppCompatActivity implements CreateToken.ICreateToken {
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
CreateToken token = new CreateToken(MainActivity.this);
textView.setText(token.toString());
}
#Override
public void onTokenGenerated(String token) {
}
}
You must call api like below for sending request to server:
CreateToken tokenCreator = new CreateToken(MainActivity.this);
tokenCreator.api(this);
and wait to triggered onTokenGenerated and using String token
#Override
public void onTokenGenerated(String token) {
textView.setText(token.toString());
}
You should have access to yourToken in MainActivity in
#Override
public void onTokenGenerated(String token) {
}
when listener.onTokenGenerated(yourToken); in CreateToken is executed. Just call public Call<Token> api(final Context ctx) method, and receive your token in MainActivity.

How can I get token with Retrofit2?

I have a web service link for token login. But in this link, there is no "/" at the end of link. And android studio make error called baseUrl must end in /. When I put / it don't get token and say token is not truth :( because the link is not correct in my think. I use retrofit2library. Please help me to solve it.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://website.net/token")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
UserClient userClient = retrofit.create(UserClient.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button loginButton=(Button)findViewById(R.id.btn_login);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
/* Intent intentLogin=new Intent(MainActivity.this,MainPageActivity.class);
startActivity(intentLogin);*/
}
});
}
private static String token;
private void login() {
Login login = new Login("abcd", "1234");
Call<User> call = userClient.login(login);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()){
Toast.makeText(MainActivity.this, response.body().getToken(), Toast.LENGTH_SHORT).show();
token = response.body().getToken();
}
else {
Toast.makeText(MainActivity.this, "Token is not truth :(", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Toast.makeText(MainActivity.this, "error!", Toast.LENGTH_SHORT).show();
}
});
}
}
`Login.java
public class Login {
private String user;
private String password;
public Login(String user, String password) {
this.user = user;
this.password = password;
}
}
User.java
public class User {
private int id;
private String email;
private String token;
public int getId(){
return id;
}
public void setId(){
this.id = id;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email = email;
}
public String getToken(){return token;}
public void setToken(String token){this.token = token;}
}
UserClient.java
import com.squareup.okhttp.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.POST;
public interface UserClient {
#POST("Login")
Call<User> login(#Body Login login);
// #GET("secretinfo")
// Call<ResponseBody> getSecret(#Header("Authorization") String authToken);
}
Use upto this in
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://website.net/")
.addConverterFactory(GsonConverterFactory.create());
and in the UserClient interface class
public interface UserClient {
#POST("token") Call<User> login(#Body Login login);
}

Retrofit method response reusing into another activity

How can I get the data from getDataForId(Integer.toString(1)); by calling the same getDataForId method from the DisplayData class?
I want reuse the same method and get the result.
It doesn't make sense to copy and paste the same method into the other activity class. Then there will be the same code repeated twice.
This is my DisplayData.class
public class DisplayData extends AppCompatActivity {
Detail reqDetail;
String BASE_URL = "";
TextView name;
ImageView image;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.display_data);
name = (TextView) findViewById(R.id.name);
image = (ImageView)findViewById(R.id.image);
public void getDataForId(final String id) {
ApiInterface apiInterface = APIClient.getApiInterface();
Call<MyResponse> call = apiInterface.getResponse();
call.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if (response.body() != null) {
MyResponse myResponse = response.body();
List<Detail> details = myResponse.getDetails();
for (Detail d : details) {
if (d.getId().equals(id)) {
reqDetail = d;
name.setText(reqDetail.getName());
Picasso.with(DisplayData.this)
.load(reqDetail.getName())
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(image);
}
}
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t) {
}
});
}
This is my SecondData class where I want to display the same data response of DisplayData by reusing same methods
public class SecondData extends AppCompatActivity {
Detail reqDetail;
String BASE_URL = "";
TextView name;
ImageView image;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_main);
name = (TextView) findViewById(R.id.name);
image = (ImageView)findViewById(R.id.image);
}
}
Create a class to make retrofit call like this
public class SampleClass {
private DataInterface mListener;
public SampleClass() {
super();
}
public void getDataForId(final String id) {
ApiInterface apiInterface = APIClient.getApiInterface();
Call<MyResponse> call = apiInterface.getResponse();
call.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if (response!=null && response.body() != null && mListener != null) {
mListener.responseData(response.body());
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t) {
}
});
}
public void setOnDataListener(DataInterface listener) {
mListener = listener;
}
public interface DataInterface {
void responseData( MyResponse myResponse );
}
}
And in your activity just call the class like this
SampleClass sampleClass = new SampleClass();
sampleClass.setOnDataListener(new SampleClass.DataInterface() {
#Override
public void responseData(MyResponse myResponse) {
}
});
sampleClass.getDataForId("UR ID");
Also in your class store the ID as private memeber variable
private Integer YOUR_ID;
Then on getting the result compare the result ID with this ID
List<Detail> details = myResponse.getDetails();
for (Detail d : details) {
if (d.getId().equals(YOUR_ID)) {
reqDetail = d;
name.setText(reqDetail.getName());
Picasso.with(DisplayData.this)
.load(reqDetail.getName())
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(image);
}
}
You should create a BaseActivity and extend the other two from it. Then, you place the method you want to use in both of them in the BaseActivity and make it public so you can use it properly.
Note that anything you need in your method from outside it won't be available in the BaseActivity, so you should either pass in the constructor or declare it in the BaseActivity if possible.
You should also think on how the return of your method should be for you to have access to its results.
You can refer to this question to learn more:
trying not to repeat myself (android/java)
So, If you want to use response of one Activity to another Activity,
Then, First save response to List or ArrayList.
And Then Pass data Using Intent.
That should do a trick.

Categories

Resources