0

I am trying to send a POST request to a php file and when the user is asked for login information, if wrong, it prints the json message from the php file and if right, it allows user to login. However, my application crashes, giving a NetworkOnThreadMainException pointing errors to three lines.

 HttpResponse response=httpClient.execute(httpPost);

public class LoginActivity extends ActionBarActivity  {

login();

So how can i make this possible? This is some part of the code I have written:

public class LoginActivity extends ActionBarActivity  {
EditText et, et2;
ImageButton ib5;
String name,pwd;

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

    et = (EditText) findViewById(R.id.editText);
    et2 = (EditText) findViewById(R.id.editText2);
    ib5 = (ImageButton) findViewById(R.id.imageButton5);

    name=et.getText().toString();
    pwd=et2.getText().toString();
    final LoginActivity loginActivity=null;

    ib5.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //login();
            new DownloadFilesTask(loginActivity,name,pwd).doInBackground();
        }
    });

}

public void login() {
    new LoginTask(this, et.getText().toString(), et2.getText().toString());
}


private class LoginTask {
    public LoginTask(LoginActivity loginActivity, String name, String pwd) {
    }
}

void navigatetoMainActivity() {
    Intent homeIntent = new Intent(getApplicationContext(), MainActivity.class);
    homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(homeIntent);
}

void InvalidToast(){
    Toast.makeText(getApplicationContext(), "Please enter valid name and password", Toast.LENGTH_LONG).show();
}
void EmptyToast(){
    Toast.makeText(getApplicationContext(), "Please fill the form, don't leave any field blank", Toast.LENGTH_LONG).show();
}
}

DownloadFilesTask.java

public class DownloadFilesTask extends AsyncTask<String, String, String> {

private String name, pwd;
private LoginActivity loginActivity;

public DownloadFilesTask(LoginActivity loginActivity,String name, String pwd){
    this.loginActivity=loginActivity;
    this.name=name;
    this.pwd=pwd;
}

@Override
protected String doInBackground(String... strings) {
    HttpClient httpClient=new DefaultHttpClient();
    HttpPost httpPost=new HttpPost("login.php");
    List<NameValuePair> nameValuePairs=new ArrayList<NameValuePair>(2);
    String result=null;
    nameValuePairs.add(new BasicNameValuePair("name", name));
    nameValuePairs.add(new BasicNameValuePair("password", pwd));
    try {
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    HttpResponse response= null;
    try {
        response = httpClient.execute(httpPost);  //error is given here
    } catch (IOException e) {
        e.printStackTrace();
    }
    HttpEntity entity=response.getEntity();
    InputStream instream= null;
    try {
        instream = entity.getContent();
    } catch (IOException e) {
        e.printStackTrace();
    }
    result=convertStreamToString(instream);
    try {
        instream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }



    if (Utility.isNotNull(name) && Utility.isNotNull(pwd)) {
        RequestParams params = new RequestParams();
        if (Utility.validate(name, pwd)) {
            params.put("username", name);
            params.put("password", pwd);
            onPostExecute();
        } else {
            loginActivity.InvalidToast();
        }
    } else {
        loginActivity.EmptyToast();
    }
    return result;
}


private String convertStreamToString(InputStream instream) {
    BufferedReader reader=new BufferedReader(new InputStreamReader(instream));
    StringBuilder sb=new StringBuilder();
    String line=null;
    try {
        while ((line=reader.readLine())!=null){
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        try {
            instream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}

protected void onPostExecute(){
    loginActivity.navigatetoMainActivity();
}



private static class Utility {
    static Pattern pattern;
    static Matcher matcher;
    static Pattern pattern1;
    static Matcher matcher1;
    static String NAME_PATTERN="SuperBoise";
    static String PWD_PATTERN="qwerty";

    public static boolean validate(String name,String pwd){
        pattern=Pattern.compile(NAME_PATTERN);
        pattern1=Pattern.compile(PWD_PATTERN);
        matcher=pattern.matcher(name);
        matcher1=pattern1.matcher(pwd);
        return matcher.matches()&& matcher1.matches();
    }

    public static boolean isNotNull(String name) {
        return name!=null && name.trim().length()>0 ? true: false;
    }
}
}
Aria
  • 389
  • 3
  • 7
  • 25
  • Possible duplicate of [android.os.NetworkOnMainThreadException](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) – ArtKorchagin Nov 09 '15 at 18:19
  • @arthurkorchagin did you read the question? you should pay more attention bc none of those questions are related – Aria Nov 09 '15 at 18:24
  • @Aria are you sure it's not network on main thread exception? I could give you an easy way to use the async task without the use of any sharedPreferences – Andrew V Nov 09 '15 at 18:28
  • @andrewv yes it is, sorry i left out that one word. what do you suggest i do? – Aria Nov 09 '15 at 18:30
  • i could format my suggestion as an answer, by showing you how to use the async task properly? do you want that? – Andrew V Nov 09 '15 at 18:30
  • @andrewv yes, please. thank you – Aria Nov 09 '15 at 18:30

1 Answers1

1

Your application has 1 main thread running all the time when it is not paused which is called the UI Thread.

As of the latest versions of Android, you are not permitted to make any network related actions on the UI Thread because it is time-consuming and it blocks the main thread which is responsible for drawing all the UI and registering the clicks, etc. (there is a way to bypass this but it is HIGHLY NOT RECOMMENDED)

An easy way to perform network related actions such as logging in, is the AsyncTask class implemented by Android.

The class runs on a very simple principle, it has 2 methods which run on the UI Thread: the onPreExecute() and the onPostExecute() methods.

And it has a method that runs on a Background Thread which is called the doInBackground() (this is where you should do all your network related actions

Here is a very basic example of an AsyncTask class:

 public class DownloadFilesTask extends AsyncTask<void, void, void> {

     public DownloadFilesTask(){
          // Here you can pass data to the task
          // if you want to pass more than 1 type of data
     }

     protected void onPreExecute(){
         // this is executed on the UI Thread 
         // so you can modify elements inside the UI Thread
         // this is called after execute() is called and 
         // before doInBackground() is called
     }

     protected void doInBackground(Void... params) {
         //here you do all your network related stuff
         return null;
     }

     protected void onPostExecute(Void result) {
         // here you can work on the UI Thread
         // this is executed after the AsyncTask's execute() is finished
         // (after doInBackground() is done)
     }
 }

And to use this task you can just simply call it from the UI Thread like this:

new DownloadFilesTask().execute();

This is the AsyncTask documentation page on the developer.android.com: AsyncTask

You could pass a reference to your LoginActivity through the constructor of the task and if the login is valid then you can call the navigatetoMainActivity() method from your onPostExecute() inside the task

Edit1: How your LoginActivity should look:

public class LoginActivity extends ActionBarActivity  {
EditText et, et2;
ImageButton ib5;

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

    et = (EditText) findViewById(R.id.editText);
    et2 = (EditText) findViewById(R.id.editText2);
    ib5 = (ImageButton) findViewById(R.id.imageButton5);

    ib5.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            login();
        }
    });
}

public void login(){
    new LoginTask(this, et.getText().toString(), et2.getText.toString()).execute();
}
}

Edit2: This is how your task should look like:

public class LoginTask extends AsyncTask<void , void, void> {

private String user, password;
private LoginActivity loginActivity;

public LoginTask(LoginActivity loginActivity, String user, String password){
     this.loginActivity = loginActivity;
     this.user = user;
     this.password = password;
}
@Override
protected String doInBackground(Void... params) {
     //do all the networking here
}

protected void onPostExecute(Void results){
     super.onPostExecute(results);
     loginActivity.navigatetoMainActivity();
}
}
Andrew V
  • 522
  • 10
  • 24
  • ok so just so i'm clear, from your answer, I would need to create a new separate class called DownloadFilesTask(), and then when the login in the Login.java is clicked, it calls the DownloadFilesTask()? would i not need to use sharedpreferences to get the username and password from the edit texts in the Login.java? that won't work in an asynctask class – Aria Nov 09 '15 at 18:57
  • Why don't you create a reference to the EditText in the LoginActivity and pass them through the constructor of the AsyncTask like : `new LoginTask(userEditText.getText().toString(), passwordEditText.getText().toString()).execute();` – Andrew V Nov 09 '15 at 18:59
  • And yes, you have to create a separate class that you can name whatever you want, but it should `extend AsyncTask `(params, progress and result can be nulled like I suggested before) – Andrew V Nov 09 '15 at 19:03
  • ok, i have edited what i have now but my editTexts still give an error – Aria Nov 09 '15 at 19:23
  • I made a very basic structure for your application, hopefully this makes it clear for you. – Andrew V Nov 09 '15 at 19:37
  • thank you very much! This helped me a lot. I still have an error but I think it is something else with my code. – Aria Nov 09 '15 at 20:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94643/discussion-between-andrew-v-and-aria). – Andrew V Nov 09 '15 at 20:43