Search code examples
javaandroidandroid-serviceandroid-context

Error trying to launch service from non-activity class


I previously had a Foreground service that I launched from one activity. The code to launch the service was contained within said activity.

Now I would like to launch this service with a non-activity class that can be called from different activities. In doing this I get an error:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.ComponentName android.content.Context.startService(android.content.Intent)' on a null object reference

The working code block was previously contained in the singular activity (let's call it 'ActivityClass') and looked like this:

private void serviceWrapper(String command){
        Intent service = new Intent(ActivityClass.this, Recorder.class);
        switch (command){
            case "start":
                    service.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
                    service.putExtra("recordAudio", RECORD_AUDIO);
                    startService(service);
                    break;
            etc...
         }
}

My attempt to move this to a non-activity class looks like this:

public class ServiceWrapper extends AppCompatActivity {
   // variable to hold context passed
   private Context context;
   public ServiceWrapper(Context context){
      this.context=context;
   }
   public void serviceControl(String command){
        Intent service = new Intent(context, Recorder.class);
        switch (command)
        {
            case "start":
                    service.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
                    service.putExtra("recordAudio", RECORD_AUDIO);
                    startService(service);
                    break;
            etc....
        }

I'd like to call this from multiple activities like this:

    private void startWrapper() {
        //Instantiate the class
        ServiceWrapper serviceWrapper = new ServiceWrapper(ActivityClass.this);
        //Check for permissions needed
        if (hasPermissionsGranted(Constants.PERMISSION_SETTINGS.VIDEO_PERMISSIONS)){
            serviceWrapper.serviceControl("start");
        }
        else {
            //kick off async request for permission
            ActivityCompat.requestPermissions(this, Constants.PERMISSION_SETTINGS.VIDEO_PERMISSIONS, REQUEST_VIDEO_PERMISSIONS);
        }
    }

But unfortunately I get this error. I'm not a super knowledgeable programmer so forgive me if this is obvious.


Solution

  • Generally this isn't the way to start a foreground service on android.

    Should be something like:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(new Intent(context, HelloService.class));
     } else {
                context.startService(new Intent(context, HelloService.class));
            }
    

    If you're outside an activity you need a way to retrieve application context. Generally that would be done by storing context as a variable via the constructor so you can use it later. E.g create a new class instance storing application context as a variable, start service using that context elsewhere in the application.

    Or depending on what your class extends or implements

    getActivity().getApplicationContext();
    

    If you're using an intent service, you should first start the service so it's initialized and pass your intents after.