Post Data To Server Using MVP Android - android

I am learning MVP design for the Android , I am new to it so need your valuable time . I went to the basics of the MVP how it work , Now i got stuck so need your help , I have to post the data to the server , when i hard code the value in presenter then i get the response correct but i need the data that is in the LoginActivity view when user press then that value should pass to the presenter and presenter pass that value to the Retrofit and bring back the result . Here is my try :
My LoginActvity:
public class LoginActivity extends BaseActivity implements LoginView {
#BindView(R.id.company_name)
protected EditText companyName_et;
#BindView(R.id.email)
protected EditText email_et;
#BindView(R.id.password)
protected EditText password_et;
#BindView(R.id.submit)
protected Button submit_btn;
#Inject
LoginPresenter loginPresenter;
#Override
protected int getContentView() {
return R.layout.login_activity;
}
#Override
protected void onViewReady(Bundle savedInstanceState, Intent intent) {
super.onViewReady(savedInstanceState, intent);
submit_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String company=companyName_et.getText().toString();
String username=email_et.getText().toString();
String password=password_et.getText().toString();
/*
I have to put the above String data
to my model class then i have to post the data to the server
*/
loginPresenter.passLoginDataToServer();
}
});
}
#Override
public void onError(String s) {
Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
}
#Override
public void onSuccess(String s) {
}
#Override
public void onResponse(Login login) {
Log.e("-----",""+login.getUserId());
}
#Override
protected void resolveDaggerDependency() {
DaggerLoginComponent.builder().applicationComponent(getApplicationComponent()).loginModule(new LoginModule(this)).build().inject(this);
}
}
Here is Login Presenter :
public class LoginPresenter extends BasePresenter<LoginView> implements Observer<Login>{
#Inject
CreateApiService createApiService;
#Inject
public LoginPresenter(){};
public void passLoginDataToServer(){
/*
when i hard code the data , i get the successful response.Like :
String user="raj";
String check="true";
Map<String,String> headers=new HashMap();
headers,put("xyz","pqr");
Login loginObject = new Login("xyzs", "pqr","Qtch","mvp");
*/
/*
But I need the data here from my LoginActivity ? Dunno how to pass the data from LoginActivity to presenter
*/
Observable<Login> loginObservable=createApiService.loginUser(user, check, headers, loginObject);
subscribeToLogin(loginObservable,this);
}
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Login login) {
getmView().onResponse(login);
}
#Override
public void onError(Throwable e) {
getmView().onError("Error "+e);
Log.e("---",""+e);
}
#Override
public void onComplete() {
getmView().onSuccess("Successfully Loaded");
}
}
Here is My Interface :
public interface LoginView extends BaseView {
void onError(String s);
void onSuccess(String s);
void onResponse(Login login);
}

Could you add the parameters to the method?
In your activity:
#Override public void onClick(View view) {
String company=companyName_et.getText().toString();
String username=email_et.getText().toString();
String password=password_et.getText().toString();
loginPresenter.passLoginDataToServer(compay, username, password);
}
In your presenter:
public void passLoginDataToServer(String company, String username, String password){
// Now create your request from the dynamic parameters
Observable<Login> loginObservable=createApiService.loginUser(username, check, headers, loginObject);
subscribeToLogin(loginObservable,this);
}

Related

Android, showProgress() and hideProgress() properly

I'm new on android development, so decided to learn simple login using MVP architectural pattern, in general everything is working fine, as checking user credentials, calling repository...etc.
However, only the implementations of showProgress() & hideProgress() that works in a weird way, for me at least.
Note that the showProgress() only works if the user inter valid credentials.
Thanks.
// Presenter Class
package com.example.mvp.login;
import android.util.Log;
import com.example.mvp.login.LoginContract;
import com.example.mvp.utils.SharedPrefManager;
public class LoginPresenterImpl implements LoginContract.Presenter{
SharedPrefManager sharedPrefManager;
private LoginContract.View view;
private LoginContract.Service service;
public LoginPresenterImpl(LoginContract.View view, LoginContract.Service service) {
this.view = view;
this.service = service;
sharedPrefManager = SharedPrefManager.getInstance(view.getContext());
}
#Override
public void onLoginClicked() {
String username = view.getUsername();
if (username.isEmpty()){
view.showUsernameError();
view.hideProgress();
return;
}
String password = view.getPassword();
if (password.isEmpty()){
view.showPasswordError();
view.hideProgress();
return;
}
view.showProgress(); // this method is called, but doesn't show in the UI Thread
boolean loginSucceeded = service.login(username, password);
if (loginSucceeded){
sharedPrefManager.userLogin(username);
view.navigateHome();
return;
}
view.hideProgress();
view.showLoginError();
}
#Override
public void isUserLoggedIn() {
if(sharedPrefManager.isLoggedIn())
view.navigateHome();
}
}
// View Class
public class LoginActivity extends AppCompatActivity implements LoginContract.View{
private EditText ed_username, ed_password;
private Button login;
private TextView signUp;
private ProgressBar progressBar;
LoginContract.Presenter presenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView(this);
presenter = new LoginPresenterImpl(this, new LoignServiceImpl());
presenter.isUserLoggedIn();
login.setOnClickListener(click);
}
View.OnClickListener click = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.login:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
presenter.onLoginClicked();
}
}, 1200);
}
}
};
public void initView(LoginActivity view){
ed_username = view.findViewById(R.id.username);
ed_password = view.findViewById(R.id.password);
login = view.findViewById(R.id.login);
signUp = view.findViewById(R.id.sign_up);
progressBar = view.findViewById(R.id.progressBar);
}
#Override
public String getUsername() {
return ed_username.getText().toString();
}
#Override
public String getPassword() {
return ed_password.getText().toString();
}
#Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
#Override
public void showUsernameError() {
ed_username.setError("Must not be empty");
}
#Override
public void showPasswordError() {
ed_password.setError("Must not be empty");
}
#Override
public void navigateHome() {
Intent intent = new Intent(this, HomeActivity.class);
startActivity(intent);
finish();
}
#Override
public void showLoginError() {
Toast.makeText(this,
"User not Found",
Toast.LENGTH_SHORT).show();
}
#Override
public Context getContext() {
return this;
}
}
Thanks to h4rd4r7c0r3 and Ionut J. Bejan, for highlighting several aspects i wasn't a ware of, in particular Working Thread(UI THREAD) and Another Thread(Background Thread).
Although i don't know yet how to implement them very well, i found way after searching the internet.
The main scenario are:
When the user enter username and password, UI should show indication
(Progress Bar) checking credentialiy of the user, implementing
showProgress().
When the checking is finished, UI should stop the indication.
implementing hideProgress().
An action to be taken based on the result, for example: Navigate to
new Activity or Toast "Wrong Username/Passowrd".
//LoginActivity
#Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
// LoginPresenter
public void onLoginClicked() {
String username = view.getUsername();
if (username.isEmpty()){
view.showUsernameError();
view.hideProgress();
return;
}
String password = view.getPassword();
if (password.isEmpty()){
view.showPasswordError();
view.hideProgress();
return;
}
view.showProgress();
service.login(username,password, this);
}
#Override
public void isUserLoggedIn() {
if(sharedPrefManager.isLoggedIn())
view.navigateHome();
}
// implementing onFinished from FinishedListiner interface, to capture the result
#Override
public void onFinished(boolean bool) {
view.hideProgress();
if (bool){
sharedPrefManager.userLogin(view.getUsername());
view.navigateHome();
return;
}
view.showLoginError();
}
// Service, which will connect to the datasource
public class LoginServiceImpl implements LoginContract.Service {
UserRepository userRepository;
#Override
public void login(final String username, final String password, final FinishedListiner listener) {
userRepository = UserRepositoryImpl.getInstance();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// The method which will be used in the presenter class.
listener.onFinished(userRepository.checkUser(username, password));
}
}, 1200);
}
Try this below snippet :
Step 1:- Create BaseActivity extend to AppCompactActivity
Step 2:-Setting BaseActivity as per your requirement
Step 3:-Create Instance of your Progress Dialog
Step 4:-Create function showProgress()
Like:-
private fun showProgress(){
if(!progress.isShowing){
progress.show()
}
}
Step 5:- Create function HideProgress()
Like:-
private fun hideProgress(){
if(progress.isShowing){
progress.dismiss()
}
}
And use as per your requirement.
Your View just run presenter on another thread. See your Handler. Then it update the view and can not access to the UI. To fix this, just make sure your showProgress() is doing work on UI thread.
runOnUiThread(new Runnable() {
public void run() {
//show your proress here.
}
});

Call activity from Application

I am trying to use Digits from Twitter.
The AuthCallBack is not fired when used from activity and the recent document saying to use the AuthCallBack from the Application class.
Now I have the AuthCallBack working correctly and onSuccess I need to call a method from my MainActivity. How do I achieve it from the Application class. Kindly help. I have given the code below.
public class MyApplication extends Application {
private AuthCallback authCallback;
#Override
public void onCreate() {
super.onCreate();
authCallback = new AuthCallback() {
#Override
public void success(DigitsSession session, String phoneNumber) {
//call myFunction() from MainActivity here
}
#Override
public void failure(DigitsException exception) {
}
};
}
public AuthCallback getAuthCallback(){
return authCallback;
}
}
You can use BroadcastManager to archive the same.
Below is sample code you can use
From Application:
#Override
public void success(DigitsSession session, String phoneNumber) {
Intent intent = new Intent(Constants.FILTER_LOGIN_SUCCESS);
intent.putExtra(Constants.EXTRA_PHONE_NUMBER, phoneNumber);
LocalBroadcastManager.getInstance(mInstance).sendBroadcast(intent);
}
Activity Class :
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(SignUpActivity.this).registerReceiver(broadcastReceiver,
new IntentFilter(Constants.FILTER_LOGIN_SUCCESS));
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(SignUpActivity.this).unregisterReceiver(broadcastReceiver);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String phoneNumber = intent.getStringExtra(Constants.EXTRA_PHONE_NUMBER);
navigateToAnotherActivty();
}
};
Using interface you can achieve this
Write an interface something like this
public interface onSuccessListner {
void onSuccess(DigitsSession session,String phoneNumber);
}
Implement this interface in your Main Activity
public class MainActivity extends AppCompatActivity implements onSuccessListner{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onSuccess(DigitsSession session,String phoneNumber) {
//write your method calling or operations here
}
}
In your application class implement Application.ActivityLifecycleCallbacks to check main activity is created or not,If main activity created apply context of main activity to the listner
In on create inside your callback method call the success method of the MainActivity
public class MyApplctn extends Application implements Application.ActivityLifecycleCallbacks {
onSuccessListner onSuccessListner;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
authCallback = new AuthCallback() {
#Override
public void success(DigitsSession session, String phoneNumber) {
//call myFunction() from MainActivity here
if(onSuccessListner!=null){
onSuccessListner.onSuccess(session,phoneNumber);
}
}
#Override
public void failure(DigitsException exception) {
}
};
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity instanceof MainActivity) {
onSuccessListner= (com.mmadapps.myapplication.onSuccessListner) activity;
}
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
Hope this will help you

Register the same Callback in two different LoginButtons in Facebook SDK

I have two buttons; each one is in a different layout, but they do the same thing because they are each a LoginButton from the Facebook SDK.
Can I make the same class handle the same action on two different buttons from different layouts?
I don't like to use an inner class so that's why I've made a new private class called ButtonFacebook
loginFacebook.registerCallback(callbackManager, new ButtonFacebook ());
And the ButtonFacebook class is this
private class ButtonFacebook implements FacebookCallback<LoginResult> {
#Override
public void onSuccess(LoginResult loginResult) {
/* CODE HERE */
}
#Override
public void onCancel() {
/* CODE HERE */
}
#Override
public void onError(FacebookException error) {
/* CODE HERE*/
}
private class graphData implements GraphRequest.GraphJSONObjectCallback {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
/*CODE HERE*/
}
}
}
I want to use this class to manage two buttons, but I don't think the solution is to make a public class...
Any advice?
You are right, you can do that. Just create a public class which implements FacebookCallback<LoginResult>:
public class LoginListener implements FacebookCallback<LoginResult> {
#Override
public void onSuccess(LoginResult loginResult) {
// Handle onSuccess action
}
#Override
public void onCancel() {
// Handle onCancel action
}
#Override
public void onError(FacebookException error) {
// Handle errors
}
}
Then set that class as the callback in your LoginButton:
CallbackManager callbackManager = CallbackManager.Factory.create();
yourLoginButton.registerCallback(callbackManager, new LoginListener());

Retrofit android not working and retrofitError 401

I am using Retrofit connect electronic devices .but it responding with incorrect data.
Please suggest me some solution to this problem. Do you guys have any idea is it related to connect ?
myUrl :http://11.10.88.23/ajax_control&/
Interface Exapi
public interface ExApi {
#GET("/ajax_control&")
public void getFeed(Callback<Document> response);
}
Mainclass
public class MainActivity extends Activity implements RequestInterceptor{
Button mButton;
public static final String BASE_URL="http://11.10.88.23/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
requestData(BASE_URL);
}
});
}
private void requestData(String url){
RestAdapter adapter=new RestAdapter.Builder()
.setEndpoint(url).build();
ExApi api=adapter.create(ExApi.class);
api.getFeed(new Callback<Document>() {
#Override
public void success(Document document, Response response) {
Toast.makeText(getApplicationContext(), "value: " + document.getElementsByTagName("LED").item(0).getChildNodes().item(0).getNodeValue(), Toast.LENGTH_SHORT).show();
}
#Override
public void failure(RetrofitError retrofitError) {
Log.d("lai loi: ", retrofitError.getMessage());
}
});
}
#Override
public void intercept(RequestFacade requestFacade) {
final String author=encodeCredentialsForBasicAuthorization();
requestFacade.addHeader("Authorization", author);
}
private String encodeCredentialsForBasicAuthorization() {
final String userAndPassword = "user:admin";
return "Basic " + Base64.encodeToString(userAndPassword.getBytes(), Base64.NO_WRAP);
}
}
Error 401 unauthorized means request is denied due to invalid credentials. This kind of authentication is called Basic Authentication, and you can pass these parameters in an HTTP header as well.
Here's an article about how that can be done in Retrofit: https://futurestud.io/blog/android-basic-authentication-with-retrofit/

retrieving data from the network

I've had an interview and I was given the following code, so that the UserAPI is a utility class for retrieving data from the network.
Assume it operate with its own threading mechanism with no respect to the caller thread.
And I had to find what's wrong with the code:
public class NetworkTestActvitiy extends Activity {
private TextView userNameTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chegg_test_layout);
userNameTextView = (TextView)findViewById(R.id.userName);
}
#Override
protected void onStart() {
super.onStart();
loadUserName();
}
private void loadUserName() {
UserAPI.getInstance().getUserName(new NetworkListener() {
#Override
public void onError(ErrorMessage error) {
Logger.e("Failed to get user use: " + error.getMessage());
}
#Override
public void onSuccess(String userName) {
userNameTextView.setText(userName);
}
});
}
}
My guess would be that the call to userNameTextView.setText can not be from UI thread and has to be marshalled.

Categories

Resources