onBind() is never called in a service

你说的曾经没有我的故事 提交于 2021-02-20 06:15:59

问题


I am writing a service based app with a bound service, and the service's onBind() method never seems to be called (testing it with Toasts and Logs).

The service:

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

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

The activity:

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

Why isn't it working?


回答1:


Probably the most common source of binding silently failing is not having the service listed in the manifest. This does not raise an exception, so your app does not crash, but there should be a message (warning, IIRC) in LogCat pointing out your issue.



来源:https://stackoverflow.com/questions/15909217/onbind-is-never-called-in-a-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!