Есть одна Activity, в которой при клике на определенную кнопку выполняется AsyncTask, который в свою очередь делает запрос на API, чтобы получить токен для пользователя:
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private Button submit;
private EditText loginLabel;
private EditText passwordLabel;
private TextView errorLabel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loginLabel = (EditText) findViewById(R.id.login);
passwordLabel = (EditText) findViewById(R.id.password);
errorLabel = (TextView) findViewById(R.id.errorLabel);
submit = (Button) findViewById(R.id.button);
submit.setOnClickListener(
new View.OnClickListener()
{
@Override
public void onClick(View v) {
String login = loginLabel.getText().toString();
String password = passwordLabel.getText().toString();
// AsyncTask Execute
Auth user = new Auth();
user.execute(login, password);
String token = user.getToken();
// При попытке вывести token через out.println - NullPointerException и остановка программы.
if (token != null && !token.trim().isEmpty()) {
Intent intent = new Intent(v.getContext(), CourierActivity.class);
intent.putExtra("token", token);
startActivity(intent);
} else {
errorLabel.setText("Неправильный логин или пароль");
}
}
}
}
);
}
static class Auth extends AsyncTask<String, Void, String> {
private String token;
private String errorMessage;
@Override
protected String doInBackground(String... params) {
String query = "Здесь URL";
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(query).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
String urlParameters = "username=" + params[0] + "&password=" + params[1];
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.writeBytes(urlParameters);
dataOutputStream.flush();
dataOutputStream.close();
StringBuilder sb = new StringBuilder();
if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
return this.token = ServiceConnect.parse(sb.toString());
} else {
this.errorMessage = "fail: " + connection.getResponseCode() + ", " + connection.getResponseMessage();
}
} catch (IOException e) {
e.printStackTrace();
}
return this.token = null;
}
public String getToken() {
return this.token;
}
public String getErrorMessage() {
return this.errorMessage;
}
}
}
Код выполняется без AsyncTask, если присутствует этот код:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Но, как говорит гугл, лучше это не использовать вообще. И без этих двух строчек вылетает Exception - android.os.NetworkOnMainThreadException
.
В чем может быть ошибка? Уже что только не перепробовал. Мне нужно просто получить токен из запроса в API.
AsyncTask выполняет операцию асинхронно, это значит что вы не можете сразу же запросить у него результат. Сетевой запрос может длиться 5 секунд, например, а вы сразу пытаетесь после запуска достать значение, которого ещё нет, поэтому и null:
Auth user = new Auth();
user.execute(login, password);
String token = user.getToken();
Вы пропустили метод onPostExecute, в котором как раз и происходит возврат к MainThread. Тут и нужно выполнять обработку токена:
@Override
protected void onPostExecute(String token) {
// тут приходит то, что возвращает doInBackground
if (token != null && !token.trim().isEmpty()) {
Intent intent = new Intent(v.getContext(), CourierActivity.class);
intent.putExtra("token", token);
startActivity(intent);
} else {
errorLabel.setText("Неправильный логин или пароль");
}
}
А в doOnBackground вам нужно просто возвращать полученный токен или null если не удалось его получить
Данный вопрос возник из-за спо