OnBind () nunca se llama en un servicio

Estoy escribiendo una aplicación basada en servicios con un servicio enlazado, y el método onBind () del servicio nunca parece ser llamado (probándolo con Toasts y Logs).

El servicio:

import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.widget.Toast; import com.gmail.zack.yovel.FlickAround.MyActivity; import com.gmail.zack.yovel.FlickAround.R; import org.json.JSONArray; import org.json.JSONObject; import java.util.ArrayList; /** * Created with IntelliJ IDEA. * User: Ziky * Date: 09/04/13 * Time: 19:06 * To change this template use File | Settings | File Templates. */ public class UpdateService extends Service implements LocationListener, UpdatePhotosTask.OnHttpResponseListener { private final static String API_KEY = "5255c7b02750c0fa4b15bd8ad4ec1fb7"; private final static String GET_PHOTOS_FOR_LOCATION_SCHEMA = "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=" + API_KEY + "&lat=%d&lon=%d&format=json&nojsoncallback=1"; private static final String KEY_PHOTOS = "photos"; private static final String KEY_PHOTO = "photo"; private int NOTIFICATION = R.string.update_service_started; private NotificationManager mNManager; private LocationManager mLManager; private String mProvider; private Location mLocation; private IBinder mBinder = new LocalBinder(); private UpdatePhotosTask task; @Override public IBinder onBind(Intent intent) { Toast.makeText(this, "UpdateService.onBind()", Toast.LENGTH_LONG).show(); Log.i("test", "UpdateService.onBind()"); mLManager.requestLocationUpdates(mProvider, 0, 1000, this); return mBinder; } @Override public void onCreate() { mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); showNotification(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("LocalService", "Received start id " + startId + ": " + intent); mLManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); mProvider = mLManager.getBestProvider(criteria, false); mLocation = mLManager.getLastKnownLocation(mProvider); return START_STICKY; } @Override public void onDestroy() { mNManager.cancel(NOTIFICATION); Toast.makeText(this, R.string.update_service_stoped, Toast.LENGTH_SHORT).show(); } private void showNotification() { CharSequence text = getText(R.string.update_service_active); Notification notification = new Notification(R.drawable.refresh, text, System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MyActivity.class), 0); notification.setLatestEventInfo(this, getText(R.string.update_service_label), text, contentIntent); mNManager.notify(NOTIFICATION, notification); } @Override public void onLocationChanged(Location location) { beginUpdate(location); } private void beginUpdate(Location location) { Toast.makeText(this, "beginning update", Toast.LENGTH_LONG).show(); String url = buildUrl(location); task = new UpdatePhotosTask(this); task.execute(url); } private String buildUrl(Location location) { return String.format(GET_PHOTOS_FOR_LOCATION_SCHEMA, location.getLatitude(), location.getLongitude()); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } @Override public void onHttpResponse(ArrayList<String> responses) { if (responses.size() > 0) { String response = responses.get(0); try { JSONObject jsonObject = new JSONObject(response); jsonObject = jsonObject.getJSONObject(KEY_PHOTOS); JSONArray jsonArray = jsonObject.getJSONArray(KEY_PHOTO); ArrayList<String> photos = new ArrayList<String>(); for (int i = 0, length = jsonArray.length(); i < length; i++) { jsonObject = jsonArray.getJSONObject(i); Log.i("photo info", jsonObject.toString()); } } catch (Exception e) { e.printStackTrace(); } } } public class LocalBinder extends Binder { public UpdateService getService() { return UpdateService.this; } } } 

El AsyncTask:

 import android.os.AsyncTask; import android.util.Log; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; /** * Created with IntelliJ IDEA. * User: Ziky * Date: 09/04/13 * Time: 07:38 * To change this template use File | Settings | File Templates. */ public class UpdatePhotosTask extends AsyncTask<String, Void, ArrayList<String>> { private OnHttpResponseListener listener; public UpdatePhotosTask(OnHttpResponseListener listener) { this.listener = listener; } @Override protected ArrayList<String> doInBackground(String... urls) { ArrayList<String> responses = new ArrayList<String>(); for (String url : urls) { StringBuilder response = new StringBuilder(); DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse execute = client.execute(httpGet); StatusLine statusLine = execute.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { InputStream content = execute.getEntity().getContent(); BufferedReader buffer = new BufferedReader(new InputStreamReader(content)); String s = ""; while ((s = buffer.readLine()) != null) { response.append(s); } responses.add(response.toString()); } else { Log.e(this.getClass().toString(), "Failed to download photo list"); } } catch (IOException e) { e.printStackTrace(); } } return responses; } @Override protected void onPostExecute(ArrayList<String> responses) { listener.onHttpResponse(responses); } public interface OnHttpResponseListener { public void onHttpResponse(ArrayList<String> responses); } } 

La actividad:

 import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.StrictMode; import android.widget.Toast; import com.gmail.zack.yovel.FlickAround.background.UpdateService; public class MyActivity extends Activity { private UpdateService mUpdateService; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mUpdateService = ((UpdateService.LocalBinder) service).getService(); Toast.makeText(MyActivity.this, R.string.update_service_connected, Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName name) { mUpdateService = null; Toast.makeText(MyActivity.this, R.string.local_service_disconnected, Toast.LENGTH_SHORT).show(); } }; private boolean mIsBound; void doBindService() { Toast.makeText(this, "MyActivity.doBindService()", Toast.LENGTH_LONG).show(); bindService(new Intent(this, UpdateService.class), mConnection, BIND_AUTO_CREATE); mIsBound = true; } void doUnbindService() { if (mIsBound) { unbindService(mConnection); mIsBound = false; } } @Override protected void onDestroy() { super.onDestroy(); doUnbindService(); } /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Activate StrictMode StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll().penaltyLog().penaltyDeath().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll() .penaltyLog().penaltyDeath().build()); } @Override protected void onStart() { super.onStart(); doBindService(); } } 

¿Por qué no funciona?

Probablemente la fuente más común de vinculación silenciosamente no es tener el servicio enumerado en el manifiesto. Esto no plantea una excepción, por lo que su aplicación no se bloquea, pero debe haber un mensaje (advertencia, IIRC) en LogCat señalando su problema.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.