feat: plugin method with callback and custom return type
Feature Request
Description
I want to be able to have a custom return type with a plugin method that has a callback. According to the documentation about plugin method types the return type is a string which represents the callback id, but i want to be able to change this type when i don't need the callback id. For my use case i want to call a method which runs a task and gives status updates about it via the callback, after some time the task is expected to finish with a result which i want to receive via the resolved promise.
Platform(s)
Android
Preferred Solution
@CapacitorPlugin(name = "Example")
public class ExamplePlugin extends Plugin {
@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
public void example(PluginCall call) {
String v = call.getString("v");
call.setKeepAlive(true);
call.resolve(new JSObject().put("n", 1));
call.resolve(new JSObject().put("n", 2));
call.resolve(new JSObject().put("n", 3));
call.setKeepAlive(false);
call.resolve(new JSObject().put("i", 42).put("r", v));
}
}
I would expect when i set keep alive to true to return values via the callback and when i set it again to false the promise is resolved with my custom type.
Alternatives
@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK_WITH_PROMISE)
public void example(PluginCall call) {/* ... */}
Introduce a new method type which could be called RETURN_CALLBACK_WITH_PROMISE to allow a custom return type in the promise.
Additional Context
Web
On the web this is already possible:
import { WebPlugin } from "@capacitor/core";
interface ExampleOptions {
v: string
}
interface ExampleCallbackValue {
n: number
}
type ExampleCallback = (value: ExampleCallbackValue) => void;
interface ExampleReturnValue {
i: number,
r: string
}
interface ExamplePlugin {
example(options: ExampleOptions, callback: ExampleCallback): Promise<ExampleReturnValue>;
}
export class ExampleWeb
extends WebPlugin
implements ExamplePlugin
{
async example(options: ExampleOptions, callback: ExampleCallback): Promise<ExampleReturnValue> {
return new Promise(resolve => {
callback({ n: 1 });
callback({ n: 2 });
callback({ n: 3 });
resolve({ i: 42, r: options.v })
});
}
}
Calling the example method with the following code:
Example.example({ v: "foo" }, (value: ExampleCallbackValue) => console.log("callback", value))
.then((value: ExampleReturnValue) => console.log("resolved", value));
Prints the expected behaviour into the console:

Android
The preferred solution currently passes the object in the last call.resolve() after setting keep alive to false to the callback.
