1

I have two Application A and B.In app B I have a service that I can run it from app A. I want to send data to app B with intent but always my intent is null!

I run app B's service from app A with this Code:

 try {

      String packageName = "app_B_package";
      String appService = packageName + ".activity.InternetService";

      Intent start = new Intent();
      start.setComponent(new ComponentName(packageName, appService));
      start.putExtra("LAUNCHER_COMMAND_CLOSE" , true);
      G.context.startService(start);

    } catch (Exception e) {
      e.printStackTrace();
    }

But when service of app B will run the intent is null. This is onStart of the service in app B:

 @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);

    Log.i("LOGO_OFFICE_IN", "onStart");

    if (intent != null) {

      if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {

        Tools.clearApplicationData(InternetService.this);
        new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
      }
    }
  }

Why my intent is null all the time? I can't find it out.

Thank you for your help.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
Ehsan
  • 2,676
  • 6
  • 29
  • 56
  • 1) Use onStartCommand instead of onStart. 2) Read javadoc of both methods. When service is restarted by system the intent is null by default. – Eugen Pechanec Jan 28 '18 at 10:54
  • @EugenPechanec Then I can't send data to my service? am I right? – Ehsan Jan 28 '18 at 11:09
  • @Ehsan Look at this similar [issue](https://stackoverflow.com/questions/14182014/android-oncreate-or-onstartcommand-for-starting-service). – udit7395 Jan 28 '18 at 11:18
  • @EugenPechanec The default implementation of `onStartCommand()` calls `onStart()`, so technically (although its use is deprecated), there is nothing wrong with using `onStart()` instead. – David Wasser Jan 28 '18 at 12:28
  • Please post your manifest. Have you implemented or overridden `onStartCommand()` in your `Service`? Of course you can pass data to your `Service` in the `Intent`! – David Wasser Jan 28 '18 at 12:29
  • @DavidWasser onStart does not return a value. onStartCommand returns a constant indicating what should happen in case the system kills the service. That's why I suggested using onStartCommand instead of onStart (which was deprecated before Android 2.0) and that's why I suggested reading the javadoc - it expains all of this. Here you go: https://developer.android.com/reference/android/app/Service.html #onStart(android.content.Intent, int) – Eugen Pechanec Jan 28 '18 at 12:37
  • @EugenPechanec Your comment isn't particularly helpful to OP's posted problem. Making the changes you suggested isn't likely to solve his problem, so I think it is extraneous to the conversation. This is just my opinion, and you can ignore it if you want to. – David Wasser Jan 28 '18 at 18:27
  • @DavidWasser Null intent can only come to a service (that's the problem, right?) in case it's restarted by system and only if `onStartCommand` returns `START_STICKY`, which is the default value. [Read for yourself.](https://developer.android.com/reference/android/app/Service.html#START_STICKY) There are multiple options how service behaves when restarted. All of this becomes apparent when using up-to-date API (that is since October 26, 2009). Now I'm leaving up to OP which mode is best for them, but I guess returning `START_NOT_STICKY`, which prevents restart, would also help debugging. – Eugen Pechanec Jan 28 '18 at 18:46

1 Answers1

4

It looks like your service is type fire-and-forget - it does one quick thing and should quit immediately because it's done. Correct?

1. Don't leave your idle service running

Documentation says

If a component starts the service by calling startService() (which results in a call to onStartCommand()), the service continues to run until it stops itself with stopSelf() or another component stops it by calling stopService().

so after your workload is done call stopSelf().

When your service is not running there's nothing to restart.

2. Use correct start mode

Unless you stop it, your service is by default automatically restarted after it's killed by system (because system needed resources). The default mode is called START_STICKY and does this:

This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.

Since your service is a quick one-time job, it makes no sense for it do be restarted later at an arbitrary time.

To let Android know, you should return START_NOT_STICKY from onStartCommand.

3. Use current API

Don't use onStart, it was deprecated 9 years ago. It doesn't support start modes mentioned above. Implement onStartCommand instead. Your service would look like this:

@Override
public void onStartCommand(Intent intent, int flags, int startId) {
    // No super call.

    Log.i("LOGO_OFFICE_IN", "onStart");

    // Intent cannot be null.
    if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {
        Tools.clearApplicationData(InternetService.this);
        new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
    }

    stopSelf(); // Work is done, stop service.

    return START_NOT_STICKY; // Don't restart if killed.
}

Now that I think of it, only step 1 is absolutely necessary. Anyway, get into habit of using current APIs and finding out how things work.

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
  • Thank you for these tips I did all of them in my code, But still the Intent is null – Ehsan Jan 29 '18 at 11:59
  • @Ehsan That's... not supposed to happen. Ok, so you're sending intent from app A to app B. Does it work correctly when you send intent from app B to app B? Can you check that? What version of Android are you testing on? Go through logcat and look for anything that might be related, start by setting filter to Verbose, "service" and No filters. Put your findings in your question. – Eugen Pechanec Jan 29 '18 at 12:22
  • The following doesn't answer your question, it may however be an alternative working solution. In case you don't get the Service to work, try implementing a BroadcastReceiver instead of Service. BroadcastReceiver can never receive null intent. Use `start.setPackage("app_B_package")` to explicitly target the intent (required on Android 7+) and `context.sendBroadcast(start)`. [Read more about receivers here.](https://developer.android.com/guide/components/broadcasts.html#restricting_broadcasts_with_permissions) – Eugen Pechanec Jan 29 '18 at 12:28
  • does it cost more than a service? – Ehsan Jan 30 '18 at 05:35
  • @Ehsan It should be about equal to what you already have. You specify it in the manifest, Android instantiates it for you and it is garbage collected after work is finished. Just like your current service. – Eugen Pechanec Jan 30 '18 at 08:39
  • @ Eugen Pechanec Thank you for all these information.it Works. – Ehsan Jan 30 '18 at 09:01
  • @Ehsan Great! Feel free to post your current code as your own answer and accept it. – Eugen Pechanec Jan 30 '18 at 09:02