10

I am creating an app having a navigation drawer activity with fragments. At every cold start of the app, I am executing some initialization code where I load the following things:

  • The user session(if the user is logged in or not)
  • Registering Retrofit services
  • Getting some data from the server to proceed with startup of the app.

This is the flow of my app when doing a cold start:

  • Starting MainActivity and verifying the user session.
  • If the session is valid, then we open the CoreActivity.
  • If not, then we open the LoginActivity.

When the app is brought to the foreground after some inactivity Android tries to restart the current Activity. This means my initialization code is bypassed and CoreActivity.onCreate() is executed.

All my activities(except MainActivity) are extending the following super activity:

public abstract class MasterActivity extends AppCompatActivity {

@Override
protected final void onCreate(Bundle savedInstanceState) {
    this.supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    if (!CrmContext.getInstance().verifyContextSet(this)) {
        return;
    }
    super.onCreate(savedInstanceState);
    onCreateAfterContext(savedInstanceState);
}

In CrmContext:

public boolean verifyContextSet(final Context context) {
    boolean isContextSet = applicationContext != null;
    if (isContextSet) {
        return true;
    }
    Intent intent = new Intent(context, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    context.startActivity(intent);
    return false;
}

In verifyContextSet() I am doing some checks to be sure that the app has been correctly loaded. If the user session is not properly loaded.

My problem:

If the app is brought to the front the CoreActivity.onCreate() is executed and verifyContextSet() returns false. In this case I want to cancel the creation of CoreActivity and open MainActivity again.

When I do my verifyContextSet() before super.onCreate(), then I get this exception:

android.util.SuperNotCalledException: Activity {nl.realworks.crm/nl.realworks.crm.view.CoreActivity} did not call through to super.onCreate() at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2287) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)

I tried to execute super.onCreate() first, but then the Fragment inside the activity is created first. This means that my Fragment is recreated before my verifyContextSet() is executed.

So, If I try to cancel()/finish() the onCreate() before super.onCreate() has been called, then I get the SuperNotCalledException. If I execute super.onCreate() first, then the Fragment is initialized which is not allowed when verifyContextSet() returns false.

I want to do the following:

  • Bringing the app to the foreground
  • Check if the app has been initialized
  • If not, then finish() the current activity and then restart the app to open MainActivity.
Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
com2ghz
  • 2,706
  • 3
  • 16
  • 27

5 Answers5

1

put your checking/validating code in an Application sub class

public class MyApp extends Application {
//in your oncreate create sessions etc.

now whether MainActivity restarts or not, you have already validated.

Note: Application class' onCreate() is the firs to run before any body.

Elltz
  • 10,730
  • 4
  • 31
  • 59
  • I tried this, but it still keeps continuing starting the Activity which was opened previously. How do I prevent that the last Activity is being restarted? – com2ghz Mar 25 '16 at 14:51
1

What you need to do is to have your onCreate like this

super.onCreate();
if(<activity is not valid>) {
   startAnotherActivity()
   finish()
   return;
}

This will make sure that no other activity lifecycle method is called except onDestroy i.e. onResume, onPause, onStop, onStart.

Rahul
  • 4,699
  • 5
  • 26
  • 38
0

I think code should look like that

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Your code

}

super.onCreate(savedInstanceState) allways as first line.

Jakub S.
  • 5,580
  • 2
  • 42
  • 37
  • 2
    When I do this, then the super.onCreate() tries to resume/initialize the Fragment before my `verifyContextSet()` is executed – com2ghz Mar 25 '16 at 13:17
  • @MikeM. The previous fragment that was opened before the app went to the background. I think the code is irrelevant because I want to do my checks before my fragment get's loaded. – com2ghz Mar 25 '16 at 13:29
  • I have moved my check to Application.onCreate() but I can't interrupt the execution. It keeps trying to resume the previous Activity – com2ghz Mar 25 '16 at 15:42
0

You can use ViewModel and Observer. Basically your remaining onCreate code will only execute if Observer triggered.


onResume {

    // THIS WILL TRIGGER THE OBSERVER
    viewModel._needVerification.value = true

}

onCreate {

    super.onCreate()

    ... CREATE VIEWMODEL

    // THIS NEEDED TO HANDLE RECREATED ACTIVITY CAUSE BY SCREEN ORIENTATION ETC
    viewModel._verificationFinished.value = false

    viewModel.needVerification.observe(this, Observer{

        if (it == true) {

            verifyContextSet(final Context context) {

                if (isContextSet) {

                    if (viewModel.verificationFinished.value != true) {

                        ... DO REMAINING ONCREATE CODE 

                        viewModel._verificationFinished.value = true

                    }

                } else {

                    Start MainActivity

                }

            }

        }

  })

}
nfl-x
  • 487
  • 1
  • 6
  • 13
0

Instead of only returning from onCreate you need to finish the Activity first to stop other initialization callbacks to be triggered.

Just change this code

if (!CrmContext.getInstance().verifyContextSet(this)) {
    return;
}

to this

if (!CrmContext.getInstance().verifyContextSet(this)) {
    finish();
    return;
}
nitinkumarp
  • 2,120
  • 1
  • 21
  • 30