0

My app has one service already that handles notifications, but I need a second one that runs persistent in the background listening for incoming data from the Pebble smartwatch.

However, for some reason, even though the service is declared in the Android manifest and will launch with the app, it closes immediately and permanently.

I don't really want to use a foreground service, because I don't feel like I should have to. There are plenty of service that run quietly in the background in a persistent fashion like Facebook and Music Boss.

The service is being started in the main activity's onCreate, so why is my service being killed immediately?

From PebbleService.java:

package net.thevgc.quotes;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;

import com.getpebble.android.kit.PebbleKit;
import com.getpebble.android.kit.util.PebbleDictionary;

import java.util.UUID;

public class PebbleService extends Service {
    private PebbleKit.PebbleDataReceiver appMessageReciever;
    private static final int KEY_AUTHOR = 1;
    private static final int KEY_QUOTE = 0;
    private static final UUID WATCHAPP_UUID = UUID.fromString("18451441-8451-4418-4514-418451441845");

    public void onCreate() {
        super.onCreate();
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);

        String[] extras = (String[]) intent.getSerializableExtra("data");
        final String quote = extras[0];
        final String author = extras[1];

        // Define AppMessage behavior
        if (appMessageReciever == null) {
            appMessageReciever = new PebbleKit.PebbleDataReceiver(WATCHAPP_UUID) {

                @Override
                public void receiveData(Context context, int transactionId, PebbleDictionary data) {
                    // Always ACK
                    PebbleKit.sendAckToPebble(context, transactionId);

                    // Send KEY_QUOTE to Pebble
                    PebbleDictionary out = new PebbleDictionary();
                    out.addString(KEY_QUOTE, mainActivity.quote[0]);
                    out.addString(KEY_AUTHOR, mainActivity.quote[1]);
                    PebbleKit.sendDataToPebble(getApplicationContext(), WATCHAPP_UUID, out);
                }
            };

            // Add AppMessage capabilities
            PebbleKit.registerReceivedDataHandler(this, appMessageReciever);
        }

        return START_STICKY;
    }

    public IBinder onBind(Intent intent) {
        return null;
    }
}

From AndroidManifest.xml:

<service
        android:enabled="true"
        android:name="PebbleService" />

UPDATE: Apparently the service is running somewhere, because I fiddled with the code some and now I'm getting a null pointer, but only when I close the main activity. I'm pretty sure it's getting relaunched and can't find the extra data it needs from the main activity because that's not the intent that started it. Which means I still have to use MainActivity mainActivity = new MainActivity(); to get the string data I need.

UPDATE 2: Okay, I feel really bad for causing all this confusion. The service is running, but it's not showing up in my Settings > Apps > Running list, even under the parent activity. I know it's running, though, because it finally ticked what it was supposed to do. Guessing a weak Bluetooth connection. That being said, I'm still throwing a NullPointerException with the current code trying to receive the intent extras. I've opened a new thread for that issue, though.

Community
  • 1
  • 1
Cora
  • 269
  • 3
  • 17

1 Answers1

0

Since you are returning START_NOT_STICKY, Android will stop your Service as soon as it returns from onStartCommand(). If you want your Service to stay alive then you need to return START_STICKY from onStartCommand().

Also, your Service doesn't automatically launch with the app. It needs to be started by calling startService().

Also, as someone noted in a comment, do not create Android components using new, like this:

MainActivity mainActivity = new MainActivity();

Only Android can properly instantiate components Activity, Service, BroadcastReceiver and Provider, because they also need to have their Context set up.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • I updated my question accordingly. While I get that it's bad practice or whatever the case to call intents using `new`, if I don't it throws an error. I have to call string data from one of my internal classes. – Cora May 26 '15 at 16:25
  • No, that is the wrong approach. You should pass the data from `MainActivity` to your `Service` in the `Intent` that you pass to `startService()`. The dependency you've got from `Service` to `Activity` is wrong. – David Wasser May 26 '15 at 16:27
  • I tried to do that with the intent extras, but it throws a NullPointerException, so I'm really not sure where to proceed from here. – Cora May 26 '15 at 16:28
  • Then you aren't doing it right. There's plenty of examples on Stackoverflow about how to pass data between an `Activity` and a `Service` using extras in an `Intent. – David Wasser May 26 '15 at 16:30
  • I've updated the OP again. I looked at one earlier but it's possible that I copied something down wrong. I'll take a second look. – Cora May 26 '15 at 16:33
  • You'll need to show the code you use to put the "data" extra into the `Intent`. In any case, if you want to pass a `String` array you should use `getStringArrayExtra()` instead of `getSerializableExtra()`. – David Wasser May 26 '15 at 16:38
  • I'll make a new post. I think that would be easier than trying to modify this one around a new problem. – Cora May 26 '15 at 16:40
  • Which, of course, I can't do for another 40 minutes. – Cora May 26 '15 at 16:44
  • Anyway, I guess in the meantime here's the code. http://paste.ubuntu.com/11373780/ – Cora May 26 '15 at 16:46
  • If you add extras using `putExtra("quote", thing)` then you need to extract it like this: `String quote = intent.getStringExtra("quote")` – David Wasser May 26 '15 at 16:48
  • Yeah, I'm in the middle of refactoring some of the variable names. Those were the old ones. I think this will be a lot more helpful: http://paste.ubuntu.com/11373800/ – Cora May 26 '15 at 16:51
  • http://stackoverflow.com/questions/30465082/passing-extras-from-activity-to-intent-throws-nullpointerexception – Cora May 26 '15 at 17:25