9

我正在编写一个带有绑定服务的基于服务的应用程序,并且该服务的 onBind() 方法似乎从未被调用(使用 Toasts 和 Logs 测试它)。

服务:

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

异步任务:

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

活动:

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

为什么它不起作用?

4

1 回答 1

11

可能最常见的无提示绑定失败的原因是清单中没有列出服务。这不会引发异常,因此您的应用程序不会崩溃,但 LogCat 中应该有一条消息(警告,IIRC)指出您的问题。

于 2013-04-09T18:17:13.607 回答