I want to implement in aidl (aosp) android a callback function which shall transfer multiple values than just one. How to solve that? Using a Pair object? Or is there any other better way?
I want to implement in aidl (aosp) android a callback function which shall transfer multiple values than just one. How to solve that? Using a Pair object? Or is there any other better way?
Here is an example for implementing an AIDL callback that returns a custom object, in Java.
SomeResult.aidl
You would define an AIDL for the custom class that you want to transfer over binder.
package com.example;
parcelable SomeResult;
ISomeCallback.aidl
You would have an AIDL for your callback. Note this imports the previous AIDL for the parcelable.
package com.example;
import com.example.SomeResult;
interface ISomeCallback {
SomeResult getResult();
}
ISomeService.aidl
You would have an AIDL for your service. Your service could have some method which takes the callback as an input. Of course, it would also be possible to have a method which returns a callback, depending on what you want to do.
package com.example;
import com.example.ISomeCallback;
interface ISomeService {
void someAction(ISomeCallback callback);
}
You can then write Java classes which implement these interfaces.
SomeResult.java
The parcelable type has to implement the Parcelable interface. You have to provide implementations for how to write/read your custom class to/from a Parcel. Usually this is done by writing each member of the class to the parcel and then reading them back out again in the same order.
package com.example;
import android.os.Parcel;
import android.os.Parcelable;
public class SomeResult implements Parcelable {
private String someData1;
private String someData2;
public SomeResult(String someData1, String someData2) {
this.someData1 = someData1;
this.someData2 = someData2;
}
@Override
public int describeContents() {
return 0; // No special data, such as file descriptors
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(someData1);
out.writeString(someData2);
}
public static final Parcelable.Creator<SomeResult> CREATOR = new Parcelable.Creator() {
public SomeResult createFromParcel(Parcel in) {
return new SomeResult(in.readString(), in.readString());
}
public SomeResult[] newArray(int size) { return new SomeResult[size]; }
};
}
SomeCallback.java
In your callback you would then construct a new instance of your custom class and return it.
package com.example;
import com.example.ISomeCallback;
import com.example.SomeResult;
public class SomeCallback extends ISomeCallback.Stub {
@Override
public SomeResult getResult() {
return new SomeResult("Hello", "world!");
}
}
SomeService.java You would implement the method of the service that takes the callback. In the method, you can then invoke the callback to obtain instances of your custom class.
package com.example;
import android.os.RemoteException;
import com.example.ISomeService;
public class SomeService extends ISomeService.Stub {
@Override
public void someAction(ISomeCallback callback) throws RemoteException {
SomeResult result = callback.getResult();
// ...
}
}
To use your service, you would for example obtain a proxy object from the service manager (assuming your service runs as a system service, if your service is run by some other means, your way for obtaining the proxy object would differ). You would then construct an instance of your callback class and call the service method with your callback as parameter:
ISomeService someService = ISomeService.Stub.asInterface(
ServiceManager.getService("some_service"));
ISomeCallback someCallback = new SomeCallback();
try {
someService.someAction(someCallback);
} catch (RemoteException ex) {
// TODO Handle error
}