This is my first attempt at creating a service and incorporating it in my application. For some reason, I can’t call any of the public methods (for the location).
The Activity
public class MileageActivityV2 extends Activity {
MileageService mService;
Boolean mBound;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.example_activity);
}
@Override
protected void onStart() {
super.onStart();
// bind to MileageService
Intent intent = new Intent(this, MileageService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
mService.getCurrentLocation();
}
@Override
protected void onStop() {
super.onStop();
// unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// get the MileageService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
The Service
public class MileageService extends Service implements IMileageService{
private final IBinder binder = new LocalBinder();
private List<Location> allLocations;
private Location startLocation;
private Location lastLocation;
private Location currentLocation;
private float totalDistance = 0;
NotificationManager nMgr;
/**
* Class used for the client Binder. Since we know this service always runs
* in the same process as the clients, dealing with IPC is not necessary.
*/
public class LocalBinder extends Binder {
public MileageService getService() {
// return this instance of MileageService so clients can call public methods
return MileageService.this;
}
}
@Override
public void onCreate() {
nMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// display a notification about the service starting
showNotification();
}
@Override
public void onDestroy() {
// cancel the persistent notification
nMgr.cancel(R.string.mileage_service_started);
// tell the user we stopped
Toast.makeText(this, R.string.mileage_service_stopped, Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.mileage_service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.car_1, text, System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MileageActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.mileage_service_started), text, contentIntent);
// Send the notification.
// We use a string id because it is a unique number. We use it later to
// cancel.
nMgr.notify(R.string.mileage_service_started, notification);
}
private static final int BUMP_MSG = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BUMP_MSG:
break;
default:
super.handleMessage(msg);
}
}
};
@Override
public List<Location> getLocations() {
return this.allLocations;
}
@Override
public Location getCurrentLocation() {
return this.currentLocation;
}
@Override
public Location getStartLocation() {
return this.startLocation;
}
@Override
public Location getLastLocation() {
return this.lastLocation;
}
@Override
public Float getDistance() {
return this.totalDistance;
}
}
Your issue is that in your onStart method, your service hasn’t actually started. The call
is asynchronous. You need to wait for the service to become bound before you call any methods on this. There are many ways to do that, but the quickest would be to add the call
mService.getCurrentLocation();to the end of theonServiceConnectedmethod. Note that this is going to run on the main thread of the app so don’t do blocking operations on it.As you get further along, you may find that you need to kick off an async task from the end of teh connection to do all the work you want without affecting the ui. There are examples of that around the web.