Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 946
TyrManuZ Avatar asked May 05 '16 20:05

TyrManuZ


People also ask

How to bind service to activity Android?

To provide binding for a service, you must implement the onBind() callback method. This method returns an IBinder object that defines the programming interface that clients can use to interact with the service.

What is AIDL service in Android?

The Android Interface Definition Language (AIDL) is similar to other IDLs you might have worked with. It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC).

When would you use AIDL?

# When to use AIDLYour service wants to handle multithreading for IPC(any method defined in service can be executed simultaneously by more than one application). If you want to share data and control something in another application. You want to create some new functionalities and distribute them as a library.


1 Answers

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.

like image 54
TyrManuZ Avatar answered Sep 22 '22 13:09

TyrManuZ