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 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.
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.