In my app I'm trying to handle global exceptions using Thread.UncaughtExceptionHandler.
When my app finds any uncaught exception, I'm trying to catch it globally in the Application class and also in fragments.
My application has many fragments on an activity. If it crashes in any of the fragment I want the app to remove that fragment and it should show the previous fragment and it is working as desired. But the UI(main thread) is blocked. If I try to access anything in the main thread, it shows a dialog saying 'app is not responding'
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(TAG + "The Uncaught exception is-----------------------------------------------------------------------------");
e.printStackTrace();
if (activityContext != null){
removeTopfragment(); //removes the top most fragment
}
}
private void removeTopfragment() {
System.out.println("inside removeTopfragment");
FragmentManager manger = activityContext.getSupportFragmentManager();
FragmentTransaction ft = manger.beginTransaction();
List<Fragment> list = manger.getFragments();
//get last one
if(list.size() > 0) {
System.out.println("inside list.size() ");
Fragment topFragment = list.get(list.size() - 1);
ft.remove(topFragment);
ft.commitAllowingStateLoss();
}
}
I don't want to kill/restart the app. Please help
Related
After watching this video by the firestore team :
https://www.youtube.com/watch?v=kDZYIhNkQoM
I have tried to implement the "this" listener before "new" keyword at "OnSuccess"
As an example:
public void pullEventsFromDatabase() {
mEventRef.get().addOnSuccessListener(getActivity(), new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
if (documentSnapshots.size() <= 0) {
setNothingToShow();
Log.w(TAG, "Error getting documents. Cat might be empty");
} else {
events.clear();
for (DocumentSnapshot document : documentSnapshots) {
Event event = document.toObject(Event.class);
events.add(new Event(event.getImageUrl(), event.getTitle(), event.getSummary(), event.getembeddedIDOrPowerLinkID(), event.getLinkToEvent(), event.getLinkToFastReservation(), event.getKey(), event.getDateOfPublish()));
}
if (events != null) {
Collections.sort(events);
initEventsRecyclerView();
}
}
}
});
}
Instead of "this" I'm using the context which is "getActivity" as this function is executed at onCreateView in a fragment.
Unfortunately while trying to implement this method (only with the context, without it the function works, but it has a bit different effect) The fragment transaction breaks!
Trying to navigate between fragments will work at start but after 2 - 3 times of going through the same fragment will cause the fragment transaction to break completely and stop responding until the app will call onDestroy and onCreate again.
Thanks in advance.
There are a several questions addressing that error but none of them have had a fix that worked for this situation.
Whats happening is that we are popping a fragment (which is nested inside a featureFragment) and making a call back to the activity to remove the feature fragment and un-hide a different fragment containing a googleMap.
DetailFragment:
if (mConversationId != null) {
try {
return getLayerClient().getConversation(mConversationId);
} catch (LayerException exc) {
getFragmentManager().popBackStack();
((MainActivity) getActivity()).LayerConnectionLost();
return null;
}
Main Activity:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Only hide the map fragment in order to keep the Google Map in memory as long as possible to avoid being charged
if (fragment != mMapFragment && !mMapFragment.isHidden()) {
transaction.hide(mMapFragment);
}
// Detach the other fragment views
if (fragment != mToolsFragment && !mToolsFragment.isDetached()) {
transaction.detach(mToolsFragment);
}
if (mMessageFragment != null ) {
if (fragment != mMessageFragment && !mMessageFragment.isDetached()) {
transaction.detach(mMessageFragment);
}
}
mVisibleFragment = fragment;
if (fragment == mMapFragment) { // map fragment is hidden, so show
transaction.show(fragment).setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out).commit();
} else { // other fragments are detached, so attach
transaction.attach(fragment).setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out).commit();
}
getSupportFragmentManager().executePendingTransactions();
The Stack Trace is giving the error on the last line
getSupportFragmentManager().executePendingTransactions();
But in testing I found that it is actually this line of code which is precipitating the error.
transaction.show(fragment).setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out).commit();
Any ideas what I'm dong wrong?
AM not so good in android Fragments. We need a proper solution to solve my problem. In mother activity I've fragment A,B,C. Every fragments comes after another . First A fragment is shown and after some user input we replace it with Fragment B and Fragment A is stacked. After B is done we replace it with C Fragment and B is stacked after A. I can go back to previous fragment to Edit the Data so we are saving the user inputs.
But when I go back to Fragments always I can get all data but only can update Fragment A UI view . I can't update any ui view in Fragment B and C .
Code snippests for different portions
abid hasan: getting current object for updating
City currentCity = cityManager.getCurrentCity();
updateViews(currentCity);
checking data for this object and updating views .
public static void updateViews(City currentCity){
Log.d(TAG , "updating views for city... "+currentCity.getCityName());
if (currentCity.getCityAccommodations().size() > 0 || currentCity.getCityLocations().size() > 0 || currentCity.getHotels().size() > 0) {
viewModifyLayoutHotels.setVisibility(View.VISIBLE);
deSelectAccommodationRadioButton.setChecked(false);
} else {
viewModifyLayoutHotels.setVisibility(View.GONE);
}
if (currentCity.cityFlights.size() > 0) {
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
} else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if(currentCity.getFlightClass().equals("")){
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
}else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if (currentCity.getActivities().size() > 0) {
viewModifyLayoutActivities.setVisibility(View.VISIBLE);
deSelectActivityRadioButton.setChecked(false);
} else {
viewModifyLayoutActivities.setVisibility(View.GONE);
}
}
on back press event from the successor fragment’s onDestroy() method and getting that object from manager and updating views
public static void updateViews(City currentCity){
Log.d(TAG , "updating views for city... "+currentCity.getCityName());
if (currentCity.getCityAccommodations().size() > 0 || currentCity.getCityLocations().size() > 0 || currentCity.getHotels().size() > 0) {
viewModifyLayoutHotels.setVisibility(View.VISIBLE);
deSelectAccommodationRadioButton.setChecked(false);
} else {
viewModifyLayoutHotels.setVisibility(View.GONE);
}
if (currentCity.cityFlights.size() > 0) {
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
} else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if(currentCity.getFlightClass().equals("")){
viewModifyLayoutFlights.setVisibility(View.VISIBLE);
deSelectFlyRadioButton.setChecked(false);
}else {
viewModifyLayoutFlights.setVisibility(View.GONE);
}
if (currentCity.getActivities().size() > 0) {
viewModifyLayoutActivities.setVisibility(View.VISIBLE);
deSelectActivityRadioButton.setChecked(false);
} else {
viewModifyLayoutActivities.setVisibility(View.GONE);
}
}
before onDestroy() call I reset Those view to initial state from onStart() method
#Override
public void onStart() {
Log.d(MakeATripStepFourFragment.TAG , "calling onStart from "+TAG);
MakeATripFragmentFirstTime.destinationTextView.setText("Select experts for your trip");
resetCityPreferencesViews();
super.onStart();
}
public static void resetCityPreferencesViews() {
MakeATripStepFourFragment.deSelectFlyRadioButton.setChecked(true);
MakeATripStepFourFragment.selectFlyRadioButton.setChecked(false);
MakeATripStepFourFragment.deSelectAccommodationRadioButton.setChecked(true);
MakeATripStepFourFragment.selectAccommodationRadioButton.setChecked(false);
MakeATripStepFourFragment.deSelectActivityRadioButton.setChecked(true);
MakeATripStepFourFragment.selectActivityRadioButton.setChecked(false);
MakeATripStepFourFragment.viewModifyLayoutFlights.setVisibility(View.GONE);
MakeATripStepFourFragment.viewModifyLayoutHotels.setVisibility(View.GONE);
MakeATripStepFourFragment.viewModifyLayoutActivities.setVisibility(View.GONE);
}
for that city for those UI is not updating I use a LocalBroadcast call to Separate UI thread updating
if (!childFragment.onBackPressed()) {
// child Fragment was unable to handle the task
// It could happen when the child Fragment is last last leaf of a chain
// removing the child Fragment from stack
Log.d(MakeATripStepFourFragment.TAG , "this fragment.. "+childFragment.getClass().getSimpleName());
if(childFragment instanceof MakeATripStepFourFragment){
Log.d(MakeATripStepFourFragment.TAG ,"lets try it out");
if (cityManager.hasNextCity()) {
City currentCity = cityManager.getNextCity();
MakeATripFragmentFirstTime.destinationTextView.setText(currentCity.getCityName());
Log.d(MakeATripStepFourFragment.TAG, "updating radioButton with city.. "+currentCity.getCityName());
Intent intent = new Intent("update_radio-button");
intent.putExtra(MakeATripStepFourFragment.TAG,currentCity);
LocalBroadcastManager.getInstance(((MakeATripStepFourFragment) childFragment).getActivity()).sendBroadcast(intent);
}
}
childFragmentManager.popBackStackImmediate();
}
// either this Fragment or its child handled the task
// either way we are successful and done here
return true;
}
and in the broadcast receiver i call the updateViews() method
private BroadcastReceiver updatePreferences = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
City currentCity = (City) intent.getSerializableExtra(TAG);
Log.d(TAG , "recived call with city..."+currentCity.getCityName());
ExpertSelectorFragment.resetCityPreferencesViews();
updateViews(currentCity);
}
};
What maybe the solution I have to know . Please wanting perfect suggestion
Here on a button click looping through the city objects and adding fragment for them , if all city traversing completed then proceed to the next fragmet
case R.id.next_fragment_destination_button:
if (!cityManager.hasNextCity()) {
Log.d("status = ", "all city explored : " + cityManager.currentCityIndex);
cityManager.currentCityIndex = 0;
/*LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(messageReceiver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(accomodationAllPreferenceReciver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(activitiesForCityPreferenceReciver);
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(updatePreferences);*/
setDataToGetExperts(cityManager.getAllCities().size());
} else {
Log.d("status = ", "going to next : " + cityManager.currentCityIndex);
Log.d(TAG, "current city size " + cityManager.getCurrentCity().toString());
cityManager.getNextCity();
//we have a next city
MakeATripStepFourFragment fragment = MakeATripStepFourFragment.newInstance(0);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
// Store the Fragment in stack
transaction.addToBackStack(null);
transaction.replace(R.id.fragment_holder, fragment ,TAG);
transaction.commit();
}
break;
I was following this tutorial on youtube and ran into a problem with the end result.
The goal of the tutorial was to introduce Fragment Transactions by having these buttons that add/remove/replace fragments in a layout below the buttons. It all went smoothly until the end.
If I hit the "Add A" button, it adds the Frag_A in the layout below, if you hit remove, it disappears. However, if you hit "Add A" 2+ times, then you need to hit remove 2+ times in order to get rid of all of them. Likewise, if you hit "Add A" and then "Add B", you need to hit "Remove A" first before you can see fragment B.
At the end of the video, they included an if statement in the "Remove" methods to check whether or not the Fragment was already there.
public void RemoveA (View v) {
FragmentA FA = (FragmentA) manager.findFragmentByTag("A");
FragmentTransaction transaction = manager.beginTransaction();
if (FA != null) {
//remove the transaction and commit
}
else {
//Toast a message to say the FragmentA doesn't exist yet
}
}
So I thought I could add a similar thing into the "AddA" method to check if a FragmentA exists, then toast a message to say it's already there, and if it doesn't exist, to add it to avoid having so many of them get created when you only need 1.
public void AddA (View v) {
FragmentA FA = (FragmentA) manager.findFragmentByTag("A");
FragmentTransaction transaction = manager.beginTransaction();
if (FA != null) {
Toast.maketext(this, "Fragment already exists", Toast.LENGTH_SHORT).show());
}
else {
transaction.add(FA);
transaction.commit();
}
}
However, this made it so when you hit "AddA", the program just gives an unexpected error and quits. Looking at the Logcat (I just started learning last week so I don't know what everything means), I noticed a line mentioning a nullpointerexception at:
transaction.add(FA);
Meanwhile, IntelliJ is saying that:
if (FA != null)
Is always true, and FA == is always false. I also tried appending && isvisible but that didn't make a difference either. Is there any ideas as to why this would happen?
This is my first post and I couldn't find an answer for this on google/searching.
Looking at your code:
if (FA != null) { // here FA is not null
Toast.maketext(this, "Fragment already exists", Toast.LENGTH_SHORT).show()); }
else { // here, FA is null!
transaction.add(FA); // same as transaction.add(null);
transaction.commit();
}
In the else block, you're missing some code where you would create a new fragment in FA, before adding it to the transaction.
if (FA != null) {
Toast.maketext(this, "Fragment already exists", Toast.LENGTH_SHORT).show()); }
else {
// Create a new fragment here and set it to FA
transaction.add(FA);
transaction.commit();
}
I am working on an app and it has code in which I have extended my class with FacebookActivity and I wanted to know what does OPENED_TOKEN_UPDATED mean and when will this portion execute
if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
//WHEN THIS PORTION WILL EXECUTE
}
Facebook documents are not so good. See below code also
#Override
protected void onSessionStateChange(SessionState state, Exception exception) {
if (isResumed) { //if its a visible activity
FragmentManager manager = getSupportFragmentManager();
int backStackSize = manager.getBackStackEntryCount(); //get number of entries currently in the back-stack
for (int i = 0; i < backStackSize; i++) {
manager.popBackStack(); //clear fragment back-stack before new fragment is added
}
if (state.isOpened()) {
if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
//WHEN THIS PORTION WILL EXECUTE
}else{
//replace fragment on main with promo fragment
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.body_frame, fragments[NextFgragment]).commit();
}
} else if (state.isClosed()) {
//replace fragment on main with login fragment
}
}
}
When you initially open a session, it will be in the SessionState.OPENED state. If you make a reauthorize request, or if the token gets refreshed, then it will be in an OPENED_TOKEN_UPDATED state.
Generally you can treat both OPENED and OPENED_TOKEN_UPDATED as the same, but sometimes (like if you request more permissions), you'll want to know when the token has been updated.
You can just disable this code
if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
//WHEN THIS PORTION WILL EXECUTE
}
The documentation the SessionState.OPENED_TOKEN_UPDATED say:
"Indicates that the Session is opened and that the token has changed. In this state, the Session may be used with Request."
that portion of code is useful, if need do something when the token change