duanmei1885 2015-11-09 18:12
浏览 374
已采纳

使用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;
    }
}
}
  • 写回答

1条回答

  • dongyao1915 2015-11-09 18:45
    关注

    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();
    }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?