Issue
I have an android application I am building and one surprising thing that happens is that it crashes when I turn off airplane mode while the application is in the foreground. I tried to include logs in the various lifecycle methods for the activity (onPause
, onCreate
, onResume
) and for the fragment that's displayed the activity's onCreate
. It so happens that all these call back methods are called in the following order:
onPause
in the Displayed Fragment
onPause
in the MainActivity
onCreate
in the MainActivity
onViewCreated
in the fragment that gets displayed in the MainActivity's onCreate
onStart
in the Displayed Fragment
onStart
in the MainActivity
onResume
in the Displayed Fragment
and the app finally crashes in onPause
in the displayed Fragment due to a NullPointerException
.
I tried to trace all these callbacks and they are due to the fact that in the displayed fragment's onPause
, there are some states that I save in SharedPreferences to restore them when the fragment is resumed and apparently they raise the exception.
May you please help me understand why an application goes through all these lifecycle methods when airplane mode is turned off while the app is in the foreground and the best way to prevent the app from crashing when this happens? I have gone through several posts concerning this issue and I have not found any answer.
Here is the code
public class MainActivity extends AppCompatActivity{
public static FragmentManager fragmentManager;
public static final String LOG_TAG = "LOG_TAG";
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(LOG_TAG, "Main activity created");
super.onCreate(savedInstanceState);
// init airplane mode receiver
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
if(isAirplaneModeOn){
Log.i(LOG_TAG, "Airplane mode turned on");// handle Airplane Mode on
} else {
Log.i(LOG_TAG, "Airplane mode turned off");
}
}
};
this.registerReceiver(receiver, intentFilter);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
displayFragment(new MapFragment());
}
@Override
protected void onPause() {
super.onPause();
Log.i(LOG_TAG, "Main activity paused");
}
@Override
protected void onResume() {
super.onResume();
Log.i(LOG_TAG, "Main activity resumed");
}
public void displayFragment(Fragment fragmentActivity){
// start the transaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragmentActivity).
addToBackStack(fragmentActivity.getClass().getSimpleName()).commit();
}
}
And the fragment
public class MapsFragment extends Fragment implements
OnMapReadyCallback {
public MapsFragment() {
// Required empty public constructor
super();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_map, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
FrameLayout map_frame = view.findViewById(R.id.map_frame);
// configure map
MapView mapFragment = view.findViewById(R.id.map_view);
mapFragment.onCreate(savedInstanceState);
mapFragment.onResume();
mapFragment.getMapAsync(this);
View mapView = mapFragment.getRootView();
super.onViewCreated(mapView, savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
Log.i(LOG_TAG, "MapFragment resumed");
}
@Override
public void onPause() {
super.onPause();
Log.i(LOG_TAG, "Map fragment paused");
}
@Override
public void onMapReady(GoogleMap googleMap) {
Log.i(LOG_TAG, "onMapReadyCalled");
MapsInitializer.initialize(getActivity());
}
}
Thank you so much in advance.
Solution
I just realized that in my code, I was displaying the MapFragment in my MainActivity's onCreate which caused the app to crush. There is no way I could make the app not go through the lifecycle methods when turning off airplane mode while the app was in the foreground. However displaying the MapFragment in my MainActivity's onStart solved the problem.
@Override
protected void onStart() {
super.onStart();
if (getCurrentFragment() == null) {
displayFragment(new MapFragment(), null, false, true);
}
}
where getCurrentFragment() is a method I defined to return the fragment that is current displayed.
Answered By - mane
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.