Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service.startForeground() throws NullPointerException when run with ServiceTestCase

This is a known annoying 2-years-old Android bug.

My question is does anyone know any workaround for this problem besides modifying Android source code and compiling it again?

Here's my code for the sake of completion:

My Service subclass method that raises the NPE:

/** Shows notification of started service */
private void doStartForeground() {

    // Prepare notification
    final NotificationHelper nh = doNotification("Service started");

    // Start foreground
    startForeground(nh.getNotificationId(), nh.getNotification());
}

This is called from onCreate() method override.

And the JUnit test method:

public void test1() throws InterruptedException {
    assertTrue(context != null);
    final Intent service = new Intent();
    service.setComponent(new ComponentName(CoreService.PACKAGE_NAME,
        CoreService.SERVICE_FULL_NAME));
    IBinder binder = bindService(service);
    assertTrue(binder != null);
}

The stack trace:

java.lang.NullPointerException
at android.app.Service.startForeground(Service.java:631)
at com.blablabla.android.core.CoreService.doStartForeground(CoreService.java:82)
at com.blablabla.android.core.CoreService.onCreate(CoreService.java:149)
at android.test.ServiceTestCase.bindService(ServiceTestCase.java:234)
at com.blablabla.android.core.test.MainTest.test1(MainTest.java:37)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:537)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)

The Service starts correctly and works fine when not run through Android's JUnit.

like image 331
m0skit0 Avatar asked Nov 13 '12 09:11

m0skit0


1 Answers

I finally ended up adding a new static field in my Service:

/** JUNIT - this is for testing purposes only */
public static boolean isJUnit = false;

And check it in the onCreate() method:

// Start the service as foreground (Android should not kill this
// service)
if (!isJUnit) {
    doStartForeground();
}

Then I set this flag from JUnit's setUp():

@Override
protected void setUp() throws Exception {
    super.setUp();
    // More setup
    MyServiceClass.isJUnit = true;
}

Not most elegant solution but gets me out of the blockade.

like image 196
m0skit0 Avatar answered Oct 23 '22 23:10

m0skit0