Сбой bindService, когда startService вызывается в предыдущем действии - PullRequest
3 голосов
/ 06 февраля 2012

Я не уверен, как решить эту проблему, но в одном действии я вызываю startService, а затем немедленно вызываю для запуска следующего действия.

Это работает, служба запускается и начинает обрабатывать данные какожидается.

Я перехожу к следующему действию, и в onResume я вызываю AsyncTask, чтобы связать службу.

Итак, основной поток состоит в том, что я вызываю AsyncTask,bindService возвращает false, поэтому mConnection никогда не вызывается.

Итак, проблема в том, почему bindService возвращает false?

Причина, по которой я поместил привязку в AsyncTask, заключается в том, что у меня былопоток спит в течение 10 секунд перед привязкой, чтобы посмотреть, нужно ли сначала запустить службу.

Я также запустил службу внутри этой операции, сначала в методе onCreate, и поэтому подождал 10 секунд, но bindService все еще возвращает ложь.

private class BindServiceTask extends AsyncTask<Void, Void, Boolean> {
    protected Boolean doInBackground(Void... params) {
        return bindService(
                new Intent(IMyCallback.class.getName()),
                mConnection, Context.BIND_AUTO_CREATE);
    }
    protected void onPostExecute(Boolean b) {
        if (b) {
            Log.i(TAG, "onResume - binding succeeded");
            Toast.makeText(mContext, "Bound to service succeeded",
                    Toast.LENGTH_LONG).show();
        } else {
            Log.i(TAG, "onResume - binding failed");
            Toast.makeText(mContext, "Bound to service failed",
                    Toast.LENGTH_LONG).show();
        }
    }
}
private IMyCallback mCallback = new IMyCallback.Stub() {
    @Override
    public void dataChanged(double[] info) throws RemoteException {
        mHandler.sendMessage(mHandler.obtainMessage(LOCATION_MSG, info));
    }
};
IMyService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        Log.i(TAG, "onServiceConnected");
        mIRemoteService = IMyService.Stub.asInterface(service);
        try {
            Log.i(TAG, "registering callback");
            mIRemoteService.registerCallback(mCallback);
        } catch (RemoteException e) {
            Log.e(TAG, e.toString());
        }
    }

    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "Service has unexpectedly disconnected");
        mIRemoteService = null;
    }
};

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

Похоже, проблема связана с манифестом.

Мне не хватило фильтра намерений, чтобы сообщить системе, к каким службам может быть привязан:

    <service
        android:name=".MyService"
        android:process=":remote" >
        <intent-filter>

            <!--
                 These are the interfaces supported by the service, which
                 you can bind to.
            -->
            <action android:name="my.com.services.IMyCallback" />
            <action android:name="my.com.services.IMySecondaryService" />
            <!--
                 This is an action code you can use to select the service
                 without explicitly supplying the implementation class.
            -->
            <action android:name="my.com.activity.MY_SERVICE" />
        </intent-filter>
    </service>
1 голос
/ 06 февраля 2012

Когда вы звоните bindService(), он не обязательно возвращает ваше подключение к службе или API для доступа к службе.Это происходит асинхронно.Вам нужен обратный вызов, подобный этому:

class PictureUploadQueueServiceConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder service){
        Log.d(TAG, "PictureUpload Service Connected!");            
        pictureUploadQueueApi = PictureUploadQueueServiceApi.Stub.asInterface(service);       
    }

    public void onServiceDisconnected(ComponentName name){
        Log.d(TAG, "PictureUpload Service Connection Closed!");
        pictureUploadQueueApi = null;
    }
};

Ваш вызов для привязки должен выглядеть следующим образом:

getApplicationContext().bindService(new Intent("org.me.xxxx.PictureUploadQueueServiceApi"),
                        pictureUploadQueueServiceConnection,
                        Context.BIND_AUTO_CREATE
                );

Убедитесь, что в вашем сервисе вы реализуете API-заглушку и возвращаетеего экземпляр в вашем onBind() методе:

private PictureUploadQueueServiceApi.Stub api = new PictureUploadQueueServiceApi.Stub() {
    @Override
    public void queuePictureUpload(String remoteURI, String localURI, String target, String description, String callback) throws RemoteException {
        appendPictureUpload(remoteURI, localURI, target, description, callback);
    }
    @Override
    public boolean isEmpty() {
        return queue.size() == 0 ? true : false;
    };
};

@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "Bound Intent: " + intent);
    return api;
}

Наконец, для завершения примера файл AIDL для моего примера выглядит следующим образом:

interface PictureUploadQueueServiceApi {

        void queuePictureUpload(String remoteURI, String localURI, String target, String description, String callback);

        boolean isEmpty();

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...