Loss of links to Android service when returning to Activity after changing screen orientation

I have an Activity that starts and binds to a Service . Then I have another Activity launched from the first. Upon returning to the first Activity from the second, I need to call the Service method (it saves some data).

When viewing each Activity my Activity lifecycle methods seem to adequately cope with screen orientation changes, provided that I return to the same screen orientation before exiting the Activity .

The problem arises when I return to the first operation with a different orientation, when I left it. If this happens, I will lose the link to my Service and, therefore, will onActivityResult() NullPointerException in onActivityResult() . Therefore, if I launched the second Activity in portrait mode, switch to landscape view when viewing the second Activity and return to the first Activity in landscape mode, this will work.

What can i skip? I do not want to use the manifest file to indicate that I will handle configuration changes - it puts me as a somewhat ugly hack that does not affect the main problem. If I don’t miss anything else ...

Here are excerpts from my life cycles from the first action:

 @Override protected void onStart() { super.onStart(); // start and bind to service startService(smsIntent); connection = new SMServiceConnection(); bindService(smsIntent, connection, Context.BIND_AUTO_CREATE); } @Override protected void onRestart() { super.onRestart(); } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); sms.save(); // autosave } @Override protected void onStop() { super.onStop(); unbindService(connection); // stopService(smsIntent); //doesn't appear to have any effect } @Override protected void onDestroy() { super.onDestroy(); } 

EDIT: Here are excerpts from my SMServiceConnection class, which is a private inner class in my Activity, which extends from the custom ServiceConnection class.

 @Override public void onServiceConnected(ComponentName name, IBinder service) { super.onServiceConnected(name, service); msg("Service connected"); sms = getSMService(); if (sms != null) { String s = sms.getStuff(); //etc.; haven't listed every method invoked on sms sms.saveSurvey(); } } else { System.out.println("sms is null!"); } } @Override public void onServiceDisconnected(ComponentName name) { super.onServiceDisconnected(name); msg("Service disconnected"); } 

My ServiceConnection super complex looks something like this:

 public class MyServiceConnection implements ServiceConnection { private boolean serviceAvailable = false; private SMService sms; public void onServiceConnected(ComponentName name, IBinder service) { serviceAvailable = true; LocalBinder b = (LocalBinder) service; sms = b.getService(); } public void onServiceDisconnected(ComponentName name) { serviceAvailable = false; } public boolean isServiceAvailable() { return serviceAvailable; } public SMService getSMService() { return sms; } } 
+4
source share
1 answer

The problem may be that onActivityResult () is called before the service is bound again on return, which happens a bit after binding in onstart.

I would try one of two things:

  • Try saving data while waiting for information:

     if (sms == null) { mPendingResultCode = resultCode; mPedingResultData = new Bundle(intent.getExtras()); } else { handleData(resultCode, intent.getExtras()); } 

    And then later onServiceConnected call handleData(mPedingResultCode, mPedingResultData) if, for example, mPendingResultData != null

    And don't forget to turn off mPendingResultCode and mPendingResultData or another indicator when you are done with the data.

  • I'm not sure about this, but maybe I'll try to add data processing to the end of the event queue by doing something like this in onActivityResult:

     final Bundle data = new Bundle(intent.getExtras); new Handler().postRunnable(new Runnable() { public void run() { "do some stuff with data and resultcode (which should be final in the parameter list anyway)" } } 

As you said, you should not change the manifest so as not to recreate the orientation. This is an ugly hack that doesn't solve the problem, and I don't like when it is offered. If you do this, you still run the risk of doing the same if some other configuration has changed, for example, the language, or if the action has been temporarily destroyed by the infrastructure to save resources.

The configchanges in the manifest should only be used if you want to get callbacks to change, and not to recreate for good. cause. Laziness is not one.

+4
source

Source: https://habr.com/ru/post/1397081/


All Articles