2

I have customized Application class in my app to initialize some global objects.

But I noticed that this Application class runs not only in normal app start, but in other occasions like unit testing. This is not desirable, because those initializations in Application class may have side effects on the test results.

So is there any way in Application class to find out if the application is running for a normal usage by user, or for other purposes?

I want to achieve something like this:

public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();
        if (isNormalRun())    //<-- How to implement this?
            initGlobalObjects();
    }

    private void initGlobalObjects()
    {
        SomeClass.initializeInstance(this);
        OtherClass.initializeInstance(this);
        //...
    }
}
Mousa
  • 2,190
  • 3
  • 21
  • 34
  • 1
    Possible duplicate of [Is is possible to find out if an Android application runs as part of an instrumentation test](http://stackoverflow.com/questions/6776689/is-is-possible-to-find-out-if-an-android-application-runs-as-part-of-an-instrume) – Tobias Jan 08 '16 at 21:05
  • 1
    *This is not desirable, because those initializations in Application class may have side effects on the test results.* that can be an indication of bad design. How do they affect it exactly? – Tim Jan 08 '16 at 21:05
  • @Tim The `SomeClass` and `OtherClass` in the sample code are singletons and their instances are being created here and being used in many places, possibly including the unit under test. – Mousa Jan 08 '16 at 21:09
  • This is exactly why you should not customize `Application` or use global state. – Kevin Krumwiede Jan 08 '16 at 21:24

3 Answers3

3

You should try "Build Variants" which have been released by Google recently. You could define a new product flavour like this (example by Google):

    ...
android {
    ...
    defaultConfig { ... }
    signingConfigs { ... }
    buildTypes { ... }
    productFlavors {
        demo {
            applicationId "com.buildsystemexample.app.demo"
            versionName "1.0-demo"
        }
        full {
            applicationId "com.buildsystemexample.app.full"
            versionName "1.0-full"
        }
    }
}
...

Then add a source directory to your project. Each product flavour corresponds to a source directory below /src/. You may add resources, classes, values etc. to each flavour. To solve your specific problem you should place a Application class in every flavours source directory and develop them separate from each other.

Documentation on developer.android.com

Jonas Köritz
  • 2,606
  • 21
  • 33
1

What do you regard as 'normal run' ?

You can define a method in your Application class which you will invoke from onCreate() of your MainActivity. For example:

public class MyApplication extends Application {
    ...
    public void deferredInit() {
        // Init some variables here
    }
}

public class MainActivity extends Activity {
    ...
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        ((MyApplication) getApplication()).deferredInit();
    }
}
guy.gc
  • 3,359
  • 2
  • 24
  • 39
  • By "normal" I mean if it is launched by user; not for example by test runners. This approach is interesting. If I fail to find a direct solution, I'll use this design. – Mousa Jan 08 '16 at 21:33
0

You can use file of properties, for example in the test environment parameterize the file for test, in the production environment parameterize the file with parameter for this situation.

Marcelo Ferreira
  • 428
  • 1
  • 5
  • 20