Я пытаюсь отправить POST-запрос в php-файл, и когда у пользователя запрашивается информация для входа в систему, в случае ошибки он печатает сообщение json из php-файла и, если это так, позволяет пользователю войти в систему. Однако мое приложение вылетает, вызывая исключение NetworkOnThreadMainException, указывающее на ошибки в три строки.
HttpResponse response=httpClient.execute(httpPost);
public class LoginActivity extends ActionBarActivity {
login();
Так как я могу сделать это возможным?
Это часть кода, которую я написал:
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;
}
}
}
Ваше приложение имеет 1 основной поток, работающий все время, когда оно не приостановлено, которое называется UI Thread
,
Начиная с последних версий Android, вы не можете выполнять какие-либо действия, связанные с сетью, на UI Thread
потому что это отнимает много времени и блокирует основной поток, который отвечает за отрисовку всего пользовательского интерфейса, регистрацию кликов и т. д. (есть способ обойти это, но это HIGHLY NOT RECOMMENDED
)
Простой способ выполнить network related actions
такие как вход в систему, является AsyncTask
Класс реализован на Android.
Класс работает по очень простому принципу, он имеет 2 метода, которые работают на UI Thread
: onPreExecute()
и onPostExecute()
методы.
И у него есть метод, который работает на Background Thread
который называется doInBackground()
(это где вы должны делать все действия, связанные с сетью
Вот очень простой пример AsyncTask
учебный класс:
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)
}
}
И чтобы использовать эту задачу, вы можете просто позвонить из UI Thread
как это:
new DownloadFilesTask().execute();
Это страница документации AsyncTask на developer.android.com: AsyncTask
Вы можете передать ссылку на свой LoginActivity через конструктор задачи, и если логин действителен, вы можете вызвать navigatetoMainActivity()
метод из вашего onPostExecute()
внутри задачи
Edit1: как должна выглядеть ваша LoginActivity:
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: Вот как должна выглядеть ваша задача:
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();
}
}
Других решений пока нет …