使用HttpClient进行登录验证

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 + "
");
        }
    } 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;
    }
}
}
doutidi5037
doutidi5037 是的,请。谢谢
接近 5 年之前 回复
drpqxogph15436713
drpqxogph15436713 我可以通过向您展示如何正确使用异步任务来格式化我的建议作为答案吗?你想要那个吗?
接近 5 年之前 回复
drtldt55533
drtldt55533 是的,对不起,我遗漏了一个字。你有什么建议我这样做?
接近 5 年之前 回复
dongxia19772008
dongxia19772008 你确定它不是主线程异常上的网络吗?我可以为您提供一种简单的方法来使用异步任务,而无需使用任何sharedPreferences
接近 5 年之前 回复
duanguanzai6181
duanguanzai6181 你读过这个问题吗?你应该多加注意bc这些问题都没有关系
接近 5 年之前 回复
duanru6816
duanru6816 android.os.NetworkOnMainThreadException可能重复
接近 5 年之前 回复

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();
}
}
duanming7833
duanming7833 让我们在聊天中继续讨论。
接近 5 年之前 回复
drvntaomy06331839
drvntaomy06331839 非常感谢你! 这对我帮助很大。 我仍然有一个错误,但我认为这是我的代码的其他内容。
接近 5 年之前 回复
dongqiulei1987
dongqiulei1987 我为你的应用程序做了一个非常基本的结构,希望这能让你清楚。
接近 5 年之前 回复
dongrao9436
dongrao9436 好吧,我已经编辑了我现在拥有的东西但是我的editTexts仍然会出错
接近 5 年之前 回复
dongzhi4470
dongzhi4470 是的,你必须创建一个单独的类,你可以命名你想要的任何名称,但它应该扩展AsyncTask <Params,Progress,Result>(参数,进度和结果可以像我之前建议的那样为空)
接近 5 年之前 回复
doufan1363
doufan1363 为什么不在LoginActivity中创建对EditText的引用,并将它们传递给AsyncTask的构造函数,如:new LoginTask(userEditText.getText()。toString(),passwordEditText.getText()。toString())。execute ();
接近 5 年之前 回复
douyanjing8287
douyanjing8287 好吧所以我很清楚,从你的回答中,我需要创建一个名为DownloadFilesTask()的新单独类,然后当单击Login.java中的登录时,它会调用DownloadFilesTask()? 我不需要使用共享偏好来从Login.java中的编辑文本中获取用户名和密码吗? 这将无法在asynctask类中工作
接近 5 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐