Search code examples
androidandroid-serviceaidlandroid-service-binding

AIDL service not connecting after bindService()


I am trying to develop a setup of 2 applications (service app + client app) using AIDL. I have currently a setup of 3 modules:

  • android-agent-framework (android library module holding only the AIDL file)
  • android-agent (the service)
  • android-example-client (the client)

android-agent and android-agent-framework have a dependency to the first one to get access to the interface.

Whenever the client calls bindService() it gets false as return and in the ServiceConnection the onServiceConnected() is not called. Also in the service implementation the onBind() is not called. There is no error in the logs.

Here is the code:

android-agent activity:

public class MyCompanyStartActivity extends Activity {

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(MyCompanyStartActivity.class.toString(), "Create MyCompanyStartActivity");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ComponentName service = startService(new Intent(this, MyCompanyRequestService.class));
        Log.i("tag", service.getClassName() + "::" + service.getPackageName());
    }

}

android-agent service:

public class MyCompanyRequestService extends Service {

@Override
public IBinder onBind(Intent intent) {
    Log.i(MyCompanyRequestService.class.toString(), "Starting SmartRest Service");
    return mBinder;
}

private final IMyCompanyRequestService.Stub mBinder = new IMyCompanyRequestService.Stub() {

    @Override
    public void sendData(String xid, String authentication, String data) throws RemoteException{
        Log.i(MyCompanyRequestService.class.toString(), "sending data: " + data);
    }
};

}

android-agent manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mycompany.android.agent" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MyCompanyStartActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Services -->
        <service
            android:name="com.mycompany.android.agent.framework.MyCompanyRequestService"
            android:process=":remote"
            android:exported="true"
            android:enabled="true">
            <intent-filter>
                <action android:name="MyCompanyRequestService"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

        <!-- Permissions -->

    </application>

</manifest>

android-example-client activity:

public class ClientStarter extends Activity {

    protected IMyCompanyRequestService mycompanyRequestService = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i("tag","create client");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
    @Override
    protected void onStart() {
        super.onStart();
        if (mycompanyRequestService == null) {
            printServices();
            Intent it = new Intent("MyCompanyRequestService");
            it.setPackage("com.mycompany.android.agent.framework");
            Log.i("tag","before binding service: " + it.getAction() + "::" + it.getPackage());
            boolean serviceBinding = getApplicationContext().bindService(it, connection, Context.BIND_AUTO_CREATE);
            Log.i("tag", "service is bound: " + serviceBinding);
        }
        Handler handler = new Handler();
        handler.postDelayed(new Runner(), 10000);
    }

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

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("service", "Service connected");
            mycompanyRequestService = IMyCompanyRequestService.Stub.asInterface(service);
            Toast.makeText(getApplicationContext(), "Service Connected", Toast.LENGTH_SHORT).show();
            Log.i("service", "Service connected");
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("service", "Service disconnected");
            mycompanyRequestService = null;
            Toast.makeText(getApplicationContext(), "Service Disconnected", Toast.LENGTH_SHORT).show();
            Log.i("service", "Service disconnected");
        }
    };

    private void printServices() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            Log.d("service", service.service.getClassName());
        }
    }

    private class Runner implements Runnable {

        @Override
        public void run() {
            Log.i("tag","starting");
            LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Location loc;
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                Log.e(ClientStarter.class.toString(), "Error", e);
            }            while(true) {
                try {
                    if (mycompanyRequestService != null) {
                        loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        Log.i(ClientStarter.class.toString(), loc.getLatitude() + " - " + loc.getLongitude() + " - " + loc.getAltitude());
                        mycompanyRequestService.sendData("test", "auth", String.valueOf(loc.getLatitude()) + "," + String.valueOf(loc.getLongitude()) + "," + String.valueOf(loc.getAltitude()));
                    } else {
                        Log.i(ClientStarter.class.toString(), "service not yet available");
                    }
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    Log.e(ClientStarter.class.toString(), "Error", e);
                } catch (RemoteException e) {
                    Log.e(ClientStarter.class.toString(), "Error", e);
                }
            }
        }


    }

}

The printServices() call before trying to bind the service actually lists the service so it is running.

The log does not contain any errors and the client is in the end running in the loop but the service is still null.

Maybe someone encountered a similar issue before.


Solution

  • After going another round through all files I found my mistake.

    I needed to change:

    Intent it = new Intent("MyCompanyRequestService");
    it.setPackage("com.mycompany.android.agent.framework");
    

    to:

    Intent it = new Intent("MyCompanyRequestService");
    it.setPackage("com.mycompany.android.agent");
    

    The package of the Intent needs to match the package of the app and not the package of the service.