Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service not being created (or connecting) after bindService()

I have this simple service that broadcasts the current location of the user. I want to use the binding mechanism just to control the service life-cycle, but the service is just not starting.

What did I do wrong?

public class GPSActivity extends ListActivity {
...
protected void onResume() {
        super.onResume();

        Log.i("Service", "Service bound");
        Intent intent = new Intent(this, LocationService.class);
        bindService(intent, service_connection , Context.BIND_AUTO_CREATE);
    }

protected void onPause() {
        if (dataUpdateReceiver!=null)
            unregisterReceiver(dataUpdateReceiver);
        unbindService(service_connection);
        super.onPause();
    }
class LocationServiceConnection implements ServiceConnection{
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("Service", "Service Connected");
        }
                public void onServiceDisconnected(ComponentName name) {

        }
    }
}

LocalBinder.java

public class LocalBinder<S> extends Binder {
    private String TAG = "LocalBinder";
    private  WeakReference<S> mService;


    public LocalBinder(S service){
        mService = new WeakReference<S>(service);
    }


    public S getService() {
        return mService.get();
    }
}

LocationService.java

public class LocationService extends Service {
    public void onCreate() {
        initLocationListener();
        Log.i("Location Service","onCreate()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Location Service", "Received start id " + startId + ": " + intent);
        return START_NOT_STICKY;
    }

    private final IBinder mBinder = new LocalBinder<LocationService>(this);
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    ...

    <service android:name=".LocationService">
    </service>
</application>  

EDIT: Fixed thanks to NickT's answer.

The manifest entry did not have a intent filter or the correct name

<service
   android:enabled="true"
   android:name="com.android.gps.services.LocationService">
   <intent-filter>
          <action android:name="com.android.gps.services.LocationService" />
   </intent-filter>
</service>

And the intent I used for binding was like the ones you need to use when starting an activity. the correct one is:

Intent intent = new Intent("com.android.gps.services.LocationService");
like image 563
bughi Avatar asked May 14 '12 10:05

bughi


People also ask

Does bindService start service?

Binding to a started service As discussed in the Services document, you can create a service that is both started and bound. That is, you can start a service by calling startService() , which allows the service to run indefinitely, and you can also allow a client to bind to the service by calling bindService() .

What is the difference between startService and bindService?

Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself. A service is "bound" when an application component binds to it by calling bindService().

What is service onBind?

In other words, the system calls the service's onBind() method to generate the IBinder only when the first client binds. The system then delivers that same IBinder to all additional clients that bind to that same service, without calling onBind() again. Follow this answer to receive notifications.


2 Answers

I had my Activity implement ServiceConnection and bound like this:

bindService( new Intent( this, Service.class ), this, Context.BIND_AUTO_CREATE );

Then handled the callbacks for onServiceConnected() and onServiceDisconnected() in my Activity

like image 149
ScouseChris Avatar answered Sep 28 '22 03:09

ScouseChris


The onStartCommand will only execute if the service is explicitly started, it looks like you are just wanting to bind to it, which is fine. I don't see that you have set up the service connection properly though. I'm posting my stub program which shows how to bind to a service and call a method in the service through a binder. You may like to run this and see the sequence of the various log messages. You will obviously need to add your BroadcastReceiver and onLocationChaged code to make it useful for you.

The Activity

package com.servtest.test;

import com.servtest.test.LocationService.LocalBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class ServiceTestActivity extends Activity {

    boolean mServiceConnected = false;
    boolean mBound = false;
    private LocationService mLocnServ;

    ServiceConnection mServconn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("SVTEST", "Activity service connected");
            LocalBinder binder = (LocalBinder) service;
            mLocnServ = binder.getService();
            // Can't call this methodInTheService UNTIL IT'S BOUND!
            mLocnServ.methodInTheService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("SVTEST", "Activity service disconnected");
            mBound = false;
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.d("SVTEST", "Activity onStart");
        mServiceConnected = bindService(new Intent(
                "com.servtest.test.LOCATIONSERVICE"), mServconn,
                Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.d("SVTEST", "Activity onResume");
    }
    @Override
    public void onPause() {
        Log.d("SVTEST", "Activity onPause");
        super.onPause();
    }
    @Override
    public void onStop() {
        Log.d("SVTEST", "Activity onStop");
        if (mBound) {
            unbindService(mServconn);
            mBound = false;
        }
        super.onStop();
    }

}

The Service

package com.servtest.test;

import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class LocationService extends Service implements LocationListener {

    private final IBinder mBinder = new LocalBinder();

    @Override
    public void onLocationChanged(Location arg0) {}
    @Override
    public void onProviderDisabled(String arg0) {}
    @Override
    public void onProviderEnabled(String arg0) {}
    @Override
    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("SVTEST", "Loc service ONBIND");
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("SVTEST", "Loc service ONUNBIND");
        return super.onUnbind(intent);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Won't run unless it's EXPLICITLY STARTED
        Log.d("SVTEST", "Loc service ONSTARTCOMMAND");
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("SVTEST", "Loc service ONDESTROY");
    }

    public class LocalBinder extends Binder {
        LocationService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocationService.this;
        }
    }

    public void methodInTheService() {
        // A method you can call in the service
        Log.d("SVTEST", "Loc service EXECUTING THE METHOD");
    }
}

The Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.servtest.test"
    android:versionCode="1"
    android:versionName="1.0" >
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ServiceTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:enabled="true"
            android:name="LocationService">
            <intent-filter>
                <action android:name="com.servtest.test.LOCATIONSERVICE" />
            </intent-filter>
        </service>
    </application>
</manifest>

Hope this helps

like image 26
NickT Avatar answered Sep 28 '22 05:09

NickT