Androidx ServiceTestRule cannot find my service

2019-08-22 03:35发布

问题:

To be fair, I am not testing the service, but am using a service as part of my test classes to test a Bluetooth library. So my test class needs to create a service that invokes the Bluetooth library. The test class then needs to bind to this service to perform the tests. However, attempting to start the service always gives me the following error which leads to a Nullpointer exception

W/ActivityManager: Unable to start service Intent { cmp=com.example.androidhdpadapter.test/com.lampreynetworks.ahd.oxp.transport.BluetoothTestService } U=0: not found

At this stage, the test class is very simple:

package com.lampreynetworks.ahd.oxp.transport;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ServiceTestRule;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.TimeoutException;
import static org.junit.Assert.fail;

@RunWith(AndroidJUnit4.class)
public class AndroidServiceBluetoothAdapterTests
{
    private final static String TAG = 
            AndroidServiceBluetoothAdapterTests.class.getName();

    @Rule
    public final ServiceTestRule serviceRule = new ServiceTestRule();

    @Test
    public void testAndroidBluetoothAdapter() throws TimeoutException, InterruptedException
    {
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        Intent intent = new Intent(context, BluetoothTestService.class);
        serviceRule.startService(intent);
        Thread.sleep(12000);
        IBinder binder = serviceRule.bindService(intent);
        BluetoothTestService service = ((BluetoothTestService.TestManagerBinder) binder).getService();
        serviceRule.unbindService();
    }
}

There are NUMEROUS posts regarding problems with testing services and I have tried all of them (messing with gradle.build file dependencies, conflicts between androidx.test and android.support.test, etc.). I have also tried invoking the service in the standard manner without ServiceTestRule, but that likely failed because there is no AndroidManifest for the test that specifies the service (I don't know if that can be done).

Maybe it is not possible to use Androidx's ServiceTestRule unless one is actually testing a service that is part of an application. Here I am testing a Bluetooth Library that is typically invoked by a service, and this test service is NOT part of the library, but exists only in the androidTests directory.

The reason I am doing this is that Android has buggy Bluetooth and on some platforms, the Bluetooth spontaneously shuts down and then restarts. My Bluetooth Library tries to recover from this shutdown. The recovery works BUT for every spontaneous shutdown and recovery, I get a service leak. That is what I am trying to solve in a simplified framework instead of a full-fledged application.