I have a problem with my activity. It work well for the first time i start but after that is crashed with this
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1842)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1860)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:650)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:609)
I try add this to my activity but it not working
@Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super(). Bug on API Level > 11.
}
When i use commitAllowingStateLoss()
instead of commit()
for changing Fragment the error now is Activity has been destroy. I have to close the app. I dont know why it run only in the first time of the activity is called.
Here is my function to change the fragment
private void showWaitingFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
WaitingFragment fragment = new WaitingFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
private void showAnswerFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
AnswerFragment fragment = new AnswerFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
First i call showWattingFragment
after the server emit event on socket i call showAnswerFragment
.
The code for socket
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Log.d("socket_log", "connected");
}
}).on("quizQuestionReady", new Emitter.Listener() {
@Override
public void call(Object... args) {
showWaitingFragment();
}
}).on("quizQuestionLoaded", new Emitter.Listener() {
@Override
public void call(Object... args) {
showAnswerFragment();
}
}).on("quizEnded", new Emitter.Listener() {
@Override
public void call(Object... args) {
showResultFragment();
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {}
});
socket.connect();
As I said before this worked for the first time i start the activity, not working after i call onBackPress()
or finish()
then startActivity
again
UPDATE my activity
public class StudentQuizActivity extends AppCompatActivity {
@BindView(R.id.quiz_content_frame)
FrameLayout _frame_content;
public Socket socket;
String quiz_code;
public SharedPreferences prefs;
ProgressDialog progressDialog;
int user_id;
String token;
public int currentQuestionIndex = -1;
public int currentQuestionIndexForShowing = 0;
public int countCorrect = 0;
public boolean no_answer = true;
public ArrayList<String> answers;
public ArrayList<String> correct_answers;
public ArrayList<Boolean> corrects;
public JSONObject quizConfig;
public JSONArray quizQuestions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student_quiz);
prefs = new SecurePreferences(this);
quiz_code = prefs.getString(AppVariable.QUIZ_CODE, null);
user_id = prefs.getInt(AppVariable.USER_ID, 0);
token = prefs.getString(AppVariable.USER_TOKEN, null);
ButterKnife.bind(this);
this.setTitle("QUIZ");
// prepare spinner
progressDialog = new ProgressDialog(this, R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setCanceledOnTouchOutside(false);
prefs.edit().putString(AppVariable.QUIZ_MESSAGE, "Waiting for the quiz to start").apply();
answers = new ArrayList<>();
correct_answers = new ArrayList<>();
corrects = new ArrayList<>();
setSocket();
new GetQuizTask().execute();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super(). Bug on API Level > 11.
}
//UI
private void showWaitingFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
WaitingFragment fragment = new WaitingFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
private void showAnswerFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
AnswerFragment fragment = new AnswerFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
private void showResultFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ResultFragment fragment = new ResultFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
public void showDetailFragment() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
DetailFragment fragment = new DetailFragment();
fragmentTransaction.replace(R.id.quiz_content_frame, fragment);
fragmentTransaction.commit();
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
private class GetQuizTask extends AsyncTask<String, Void, Integer> {
private Exception exception;
private String strJsonResponse;
@Override
protected void onPreExecute() {
progressDialog.setMessage("Loading...");
progressDialog.show();
}
@Override
protected Integer doInBackground(String... params) {
int flag = 0;
try {
URL url = new URL(Network.API_GET_QUIZ);
//prepare json data
JSONObject jsonUserData = new JSONObject();
jsonUserData.put("token", token);
jsonUserData.put("quiz_code", quiz_code);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty("Accept", "application/json");
connection.setDoInput(true);
connection.setDoOutput(true);
//write
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(jsonUserData.toString());
writer.flush();
//check http response code
int status = connection.getResponseCode();
switch (status){
case HttpURLConnection.HTTP_OK:
//read response
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line).append("\n");
}
bufferedReader.close();
strJsonResponse = sb.toString();
flag = HttpURLConnection.HTTP_OK;
default:
exception = new Exception(connection.getResponseMessage());
}
}
finally{
connection.disconnect();
}
}
catch(Exception e) {
exception = e;
}
return flag;
}
@Override
protected void onPostExecute(Integer status) {
if (status != HttpURLConnection.HTTP_OK){
displayToast(exception.getMessage());
}
else {
try{
JSONObject jsonObject = new JSONObject(strJsonResponse);
String result = jsonObject.getString("result");
if (result.equals("failure")){
String message = jsonObject.getString("message");
progressDialog.dismiss();
displayToast(message);
return;
}
quizConfig = jsonObject.getJSONObject("quiz");
quizQuestions = quizConfig.getJSONArray("questions");
prefs.edit().putInt(AppVariable.QUIZ_TOTAL, quizQuestions.length())
.putString(AppVariable.QUIZ_TITLE, quizConfig.getString("title")).apply();
progressDialog.dismiss();
showWaitingFragment();
return;
} catch (JSONException e) {
e.printStackTrace();
displayToast(e.getMessage());
}
}
progressDialog.dismiss();
}
}
//Socket
private void setSocket(){
if (Network.isOnline(this)){
try {
socket = IO.socket(Network.HOST);
} catch (URISyntaxException e) {
e.printStackTrace();
}
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Log.d("socket_log", "connected");
}
}).on("quizQuestionReady", new Emitter.Listener() {
@Override
public void call(Object... args) {
currentQuestionIndexForShowing += 1;
prefs.edit().putString(AppVariable.QUIZ_MESSAGE, "Ready for the next question")
.putInt(AppVariable.QUIZ_INDEX, currentQuestionIndexForShowing).apply();
showWaitingFragment();
}
}).on("quizQuestionLoaded", new Emitter.Listener() {
@Override
public void call(Object... args) {
currentQuestionIndex += 1;
showAnswerFragment();
}
}).on("quizQuestionEnded", new Emitter.Listener() {
@Override
public void call(Object... args) {
}
}).on("quizEnded", new Emitter.Listener() {
@Override
public void call(Object... args) {
prefs.edit()
.putInt(AppVariable.QUIZ_INDEX, 0).apply();
showResultFragment();
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {}
});
socket.connect();
}
}
public void emitAnswer(String option){
JSONObject payload = new JSONObject();
try {
payload.put("quiz_code", quiz_code);
payload.put("question_index", currentQuestionIndex);
payload.put("option", option);
payload.put("student_id", user_id);
} catch (JSONException e) {
e.printStackTrace();
}
no_answer = false;
try {
JSONObject quizDetail = quizQuestions.getJSONObject(currentQuestionIndex);
String correct_option = quizDetail.getString("correct_option");
ArrayList<String> options = new ArrayList<>();
options.add(quizDetail.getString("option_a"));
options.add(quizDetail.getString("option_b"));
options.add(quizDetail.getString("option_c"));
options.add(quizDetail.getString("option_d"));
String[] keys = {"a", "b", "c", "d"};
for (int i = 0; i < 4; i++){
if (correct_option.equals(options.get(i))){
correct_option = keys[i];
break;
}
}
if (option.equals(correct_option)){
corrects.add(true);
countCorrect += 1;
}
else {
corrects.add(false);
}
correct_answers.add(correct_option);
} catch (JSONException e) {
e.printStackTrace();
}
answers.add(option);
socket.emit("answeredQuiz", payload);
}
}