android - error while committing fragment transaction from intent handler -


im trying write simple music player , faced such problem. in ui have several fragments, used different modes of displaying songs (for example, music, music selected folder, music playlist , on). have service plays music.

when user close player in playing state wanna save ui state (i.e. current displaying fragment) , restore state after opening player again (if user close player in paused state doesn't need).

for saving state use service, mentioned above. in ondestroy() method of activity put needed data restoring intent , call startservice(intent). service save data local variables. in oncreate() method of activity call startservice intent, contains request of saved state. in service put saved data intent , send activity using localbroadcastmanager.getinstance(this).sendbroadcast(intent) method. in inner broadcastlistener class of activity receive intent , extract data. seems okay.

but problems begins when trying restore fragments displaying when user close player. application crashes unhandled exception. here backstack:

java.lang.illegalstateexception: can not perform action after onsaveinstancestate         @ android.support.v4.app.fragmentmanagerimpl.checkstateloss(fragmentmanager.java:1377)         @ android.support.v4.app.fragmentmanagerimpl.enqueueaction(fragmentmanager.java:1395)         @ android.support.v4.app.backstackrecord.commitinternal(backstackrecord.java:637)         @ android.support.v4.app.backstackrecord.commit(backstackrecord.java:616)         @ com.borune.test.mainactivity.switchfragments(mainactivity.java:58)         @ com.borune.test.mainactivity$myservicelistener.onreceive(mainactivity.java:102)         @ android.support.v4.content.localbroadcastmanager.executependingbroadcasts(localbroadcastmanager.java:297)         @ android.support.v4.content.localbroadcastmanager.access$000(localbroadcastmanager.java:46)         @ android.support.v4.content.localbroadcastmanager$1.handlemessage(localbroadcastmanager.java:116)         @ android.os.handler.dispatchmessage(handler.java:102)         @ android.os.looper.loop(looper.java:136)         @ android.app.activitythread.main(activitythread.java:5032)         @ java.lang.reflect.method.invokenative(native method)         @ java.lang.reflect.method.invoke(method.java:515)         @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:785)         @ com.android.internal.os.zygoteinit.main(zygoteinit.java:601)         @ dalvik.system.nativestart.main(native method) 

i've googling exception proposed solutions didn't in case. wrote simple project repeating described problem. here code:

mainactivity.java:

public class mainactivity extends actionbaractivity {  private int current_fragment; private fragmenta fragmenta = null; private fragmentb fragmentb = null; private myservicelistener myservicelistener;  @override protected void oncreate(bundle savedinstancestate) {     super.oncreate(savedinstancestate);     setcontentview(r.layout.activity_main);     current_fragment = 1;     switchfragments(null);     myservicelistener = new myservicelistener();      localbroadcastmanager.getinstance(this).registerreceiver(myservicelistener,new intentfilter(myservice.response_restore));      requeststate(); }  public void switchfragments(view view) {     switch(current_fragment) {         case 1 : {             if(fragmenta == null) {                 fragmenta = fragmenta.newinstance();             }              fragmenttransaction transaction = getsupportfragmentmanager().begintransaction();             transaction.replace(r.id.container, fragmenta);             current_fragment = 1;             transaction.commit();              current_fragment = 2;              break;         }         case 2 : {             if(fragmentb == null) {                 fragmentb = fragmentb.newinstance();             }              fragmenttransaction transaction = getsupportfragmentmanager().begintransaction();             transaction.replace(r.id.container, fragmentb);             current_fragment = 1;             transaction.commit();              current_fragment = 1;              break;         }      } }  protected void ondestroy(){     super.ondestroy();      log.d("log", "ondestroy() called, saving fragment number");     intent intent = new intent(this,myservice.class);     intent.setaction(myservice.save_state);     intent.putextra(myservice.fragment_number,current_fragment);     startservice(intent); }   private class myservicelistener extends broadcastreceiver {      @override     public void onreceive(context context, intent intent) {         string action = intent.getaction();          if(action.equals(myservice.response_restore)) {             current_fragment = intent.getintextra(myservice.fragment_number,-1);             log.d("log", "received fragment number, restoring now");             switchfragments(null);         }     } }  private void requeststate() {     intent intent = new intent(this,myservice.class);     intent.setaction(myservice.request_restore);     startservice(intent);  }  } 

myservice.java

public class myservice extends service {  public static final string request_restore = "action.request_restore"; public static final string response_restore = "action.response_restore"; public static final string save_state = "action.save_state"; public static final string fragment_number = "fragment_number";  private int fragment_number = -1;  public myservice() { }  @override public ibinder onbind(intent intent) {     return null; }  @override public int onstartcommand(intent intent, int flags, int startid) {      string action = intent.getaction();     if(action.equals(request_restore)) {         if(fragment_number != -1)             sendstate();     } else if (action.equals(save_state)) {         fragment_number = intent.getintextra(fragment_number,-1);     }     return start_not_sticky; }  private void sendstate() {     intent intent = new intent(response_restore);     intent.putextra(fragment_number,fragment_number);     localbroadcastmanager.getinstance(this).sendbroadcast(intent);  }  } 

in app have layout container , button android:onclick="switchfragments". after closing app , opening again receive same exception.

can explain me, why error occures , how solve it?

this thread explain happens : getting exception "illegalstateexception: can not perform action after onsaveinstancestate"

short answer might dangerous : use commitallowingstateloss() instead of commit(), might break if not careful.

as did, created boolean flag called "issafetocommitfragment", set false default, assign value activity lifecycle follows :

  • ondestroy() : false
  • onpause() : false
  • onresume() : false
  • onstart() : false
  • onstop() : false
  • onpostresume() : true

before calling fragmenttransaction.commit(), check flag follows :

if (issafetocommitfragment) {     fragmenttransaction.commit(); } 

Comments

Popular posts from this blog

javascript - Google App Script ContentService downloadAsFile not working -

javascript - Function overwritting -

php - Find a regex to take part of Email -