Question

I've defined a remote service in an Android Library project using AIDL. The service is supposed to simply increment an int. I try to bind to it from another project, an application using the library. The application's call to bindService(...) always returns false. What am I doing wrong?

The main activity of the application project:

MainActivity.java

package com.example.serviceusera;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.example.service.IncService;
import com.example.service.IncServiceConnection;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private IncServiceConnection mConnection;
    private int mCount = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        try {
            mConnection = bindService();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to bind service", e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConnection);
    }

    private IncServiceConnection bindService() throws RemoteException {
        IncServiceConnection connection = new IncServiceConnection();
        Intent service = new Intent(IncService.class.getName());
        boolean bound = bindService(service, connection, Context.BIND_AUTO_CREATE);
        Log.d(TAG, "bindService() = " + bound);
        if (bound) {
            return connection;
        } else {
            throw new RemoteException("Failed to bind service");
        }
    }

    private void init() {
        // Show the current value of the counter
        final EditText text = (EditText) findViewById(R.id.editText1);
        text.setText(Integer.toString(mCount));

        // Set button to increment counter
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    mCount = mConnection.inc(mCount);
                    text.setText(Integer.toString(mCount));
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to use service", e);
                }
            }
        });

    }

}

The library project:

IIncService.aidl

package com.example.service;

interface IIncService {
    int inc(in int i);
}

IncService.java

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class IncService extends Service {

    private final IIncService.Stub mBinder = new IIncService.Stub() {
        @Override
        public int inc(int i) throws RemoteException {
            return i + 1;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

}

IncServiceConnection.java

package com.example.service;

import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;

public class IncServiceConnection implements ServiceConnection {

    private IIncService mService;

    public int inc(int i) throws RemoteException {
        return mService.inc(i);
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mService = IIncService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    }

}

I've added the service to the library's manifest:

AndroidManifest.xml

...
<application
        ...
        <service
            android:name="com.example.service.IncService"
            android:process=":remote" >
        </service>
 </application>
...

and enabled mainfest merging in the application:

project.properties

...
manifestmerger.enabled=true
Was it helpful?

Solution

I've tried Your code using IntelliJ Idea 13 and have found the issue. Firstly, I ensured that:

  1. Library project is exported;
  2. Application project has Enable manifest merging on under Android Compiler properties;

Using that configuration it didn't work and I've observed Unable to start service Intent.

The issue here is in incorrect Intent creation. Seems that class name You obtain by IncService.class.getName() doesn't specify the component completely (if logs checked it looks like so, because intent contains only class name, but package name is missed). So, to specify component properly, I've used another way:

final Intent service = new Intent(this, IncService.class);

And it worked fine.

OTHER TIPS

Instead of binding Ibinder, try using binding with Handler. I have recently done an application the way you did and I could not figure out the fault. But working with Messager made things easier. Instead of return binder object. It returns message obj. Here is the reference.

Source: Android Remote Bound Services

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top