2013-04-09 9 views
9

Sto scrivendo un'app basata sul servizio con un servizio associato e il metodo onBind() del servizio non sembra mai essere chiamato (testandolo con Toasts e Log).onBind() non viene mai chiamato in un servizio

Il servizio:

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; 
     } 
    } 
} 

L'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); 
    } 
} 

L'attività:

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(); 
    } 
} 

Perché non sta funzionando?

+2

Controllare LogCat per i messaggi, ad esempio se il proprio servizio non è elencato nel manifest. – CommonsWare

risposta

10

Probabilmente l'origine più comune del binding in mancanza di errori non sta avendo il servizio elencato nel manifest. Questo non genera un'eccezione, quindi la tua app non si blocca, ma dovrebbe esserci un messaggio (warning, IIRC) in LogCat che segnala il tuo problema.

+0

Grazie, questo era il caso - Una classe di servizio diversa era elencata nel manifest invece di questa. –