1

I am creating simple system that has a windows service running, complete with a table of users, and I want to validate someone's login credentials by sending something to the service. I am trying to send their username and password, but I keep getting an error with my Async Task. I know that you're not supposed to mess with UI stuff in there and I am not. Originally I had a call to another activity in there but I commented it out. Now the only thing in doInBackground is setting a boolean value to true if the validation was good. From there I read the value after the async has executed, and then put together a bundle to move to the next place. I just don't know what's wrong here. It has been awhile since I've programmed in Android so maybe I'm missing something stupid. If anyone could help me out I would greatly appreciate it! Thank you. This could also be an issue with sending the information to the service?

UPDATE: After adding in the internet usage in the manifest, if I have the log.d in the program in my doInBackground, it prints out. If I don't have it, the result value stays false. It looks like there is some issue with the connection between my service and android app...

import java.util.ArrayList;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class LoginActivity extends Activity {
    private static final int DATA_FROM_MAIN_ACTIVITY = 1;
    private static final String SERVICEURL = "http://localhost:56638/ClientService.svc";
    private EditText userTextBox, passTextBox;
    private Button loginButton;
    private String uName, pass;
    private Boolean result = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        userTextBox = (EditText) findViewById(R.id.userTextBox);
        passTextBox = (EditText) findViewById(R.id.passTextBox);
        loginButton = (Button) findViewById(R.id.loginButton);

        loginButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                uName = userTextBox.getText().toString();
                pass = passTextBox.getText().toString();

                SendLoginMessage task = new SendLoginMessage();
                task.execute(uName, pass);

                if (result.equals(true)) {
                    Intent goToMainScreen = new Intent(getApplicationContext(),
                            MainActivity.class);
                    goToMainScreen.putExtra("username", uName);
                    goToMainScreen.putExtra("password", pass);

                    startActivityForResult(goToMainScreen,
                            DATA_FROM_MAIN_ACTIVITY);
                } else {
                    Toast.makeText(
                            getApplicationContext(),
                            "There was an issue with your username or password.",
                            Toast.LENGTH_LONG).show();
                }

            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private class SendLoginMessage extends AsyncTask<String, String, Void> {
        @Override
        protected void onPreExecute() {
            // Log.d("message almost at server, " + textFromArea, selected,
            // null);
        }

        @Override
        protected Void doInBackground(String... names) {
            ArrayList<NameValuePair> postParams = new ArrayList<NameValuePair>();
            postParams.add(new BasicNameValuePair("username", names[0]));
            postParams.add(new BasicNameValuePair("password", names[1]));

            String response = null;

            try {
                response = HttpClient.executeHttpPost(SERVICEURL, postParams);

                String newResponse = response.toString();
                newResponse = newResponse.replaceAll("\\s+", "");

                // if user was authenticated...
                if (newResponse.equals(true)) {
                    result = true;
                    // creating an intent to take user to next page.
                    // load their DB objects on the
                    // on create in other activity
                    // pass the username/password to next activity
                    // then make a request to the server for their database
                    // objects.
                    // Intent goToMainScreen = new
                    // Intent(getApplicationContext(), MainActivity.class);
                    // goToMainScreen.putExtra("username", names[0]);
                    // goToMainScreen.putExtra("password", names[1]);

                    // startActivityForResult(goToMainScreen,
                    // DATA_FROM_MAIN_ACTIVITY);
                }

            } catch (Exception e) {
                Log.d("ERROR", "exception in background");
            }

            return null;

        }

        @Override
        protected void onPostExecute(Void result) {

            // Toast.makeText(getApplicationContext(),
            // .show();

        }

    }

}
Tastybrownies
  • 897
  • 3
  • 23
  • 49
  • What is the error you keep getting? – codeMagic Mar 13 '13 at 19:30
  • This is probably one problem `if (newResponse.equals(true))` it should be if (newResponse.equals("true")) since you are comparing `Strings` now – codeMagic Mar 13 '13 at 19:32
  • I also added the internet use in my manifest but that didn't clear things up. I also changed the .equals to a string check, but that didn't make a difference either. – Tastybrownies Mar 13 '13 at 19:36
  • I probably have to modify my web service so it knows which method the client intents to use huh? – Tastybrownies Mar 13 '13 at 19:43
  • Possibly but I would fix the other issues first. Such as the first one I named and you aren't passing the params correctly in `execute()` – codeMagic Mar 13 '13 at 19:46
  • I'm kind of surprised you say that because I debugged the code and they DID come through correctly. How would you pass them? Thank you for your help. – Tastybrownies Mar 13 '13 at 20:20
  • It has always been my understanding that they should be wrapped in a container or an `ArrayList`. That's why in the [Docs](http://developer.android.com/reference/android/os/AsyncTask.html#execute(Params...)) the method is `execute(Params...params)` – codeMagic Mar 13 '13 at 20:26
  • Okay, I'll give that a try as well. – Tastybrownies Mar 13 '13 at 20:37
  • Ok, I can post as an answer with more clarification and helpful links later when I get time if that is what works for you – codeMagic Mar 13 '13 at 20:39
  • @codeMagic his params are correct. Its called Varargs. Please read http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java – M-Wajeeh Mar 13 '13 at 20:39

1 Answers1

2

Do it like this:

 private class SendLoginMessage extends AsyncTask<String, String, Boolean> {
    @Override
    protected Boolean doInBackground(String... names) {
        ArrayList<NameValuePair> postParams = new ArrayList<NameValuePair>();
        postParams.add(new BasicNameValuePair("username", names[0]));
        postParams.add(new BasicNameValuePair("password", names[1]));

        String response = null;

        try {
            response = HttpClient.executeHttpPost(SERVICEURL, postParams);

            String newResponse = response.toString();
            newResponse = newResponse.replaceAll("\\s+", "");

            // if user was authenticated...
            if (newResponse.equals("true")) {
                return true;
            }

        } catch (Exception e) {
            Log.d("ERROR", "exception in background");
        }

        return false;

    }

    @Override
    protected void onPostExecute(Boolean result) {
            if (result) {
                Intent goToMainScreen = new Intent(getApplicationContext(),
                        MainActivity.class);
                goToMainScreen.putExtra("username", uName);
                goToMainScreen.putExtra("password", pass);

                startActivityForResult(goToMainScreen,
                        DATA_FROM_MAIN_ACTIVITY);
            } else {
                Toast.makeText(
                        getApplicationContext(),
                        "There was an issue with your username or password.",
                        Toast.LENGTH_LONG).show();
            }
    }

}

and in your onClick() just call execute()

 uName = userTextBox.getText().toString();
 pass = passTextBox.getText().toString();

 SendLoginMessage task = new SendLoginMessage();
 task.execute(uName, pass);

After execution is finished onPostExecute() will be called and your Activity will start depending on result variable.

Don't check your result variable after you invoke execute() because execute() is invoked asynchronously. By the time you check your global result variable, your doInBackground() might not have been finished. Using my approach you don't need a global variable. Please read doc carefully before using any component.

M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103
  • Hey, thank you very much for commenting on this. I learned a lot by your way of doing things. The flow is a lot smoother and it makes more sense. Thank you for covering things so nice and informative. – Tastybrownies Mar 13 '13 at 23:23