Closed Flockavelli closed 2 years ago
Any chance of this getting consideration soon @josesamuel ?
Try this --
Define your interface in the java library. It doesn't need @ Remoter annotation.
public interface IBusinessLogic {
void helloWorld();
}
In your android module, define a wrapper interface that extends the other interface and annotate that with @ Remoter. This acts like the marker interface for remoter and generates all the functions that you defined in the base interface without needing to redefine it here.
@Remoter
public interface IAndroidInterface extends IBusinessLogic {
}
How then do I bind to the remote interface?
In your kotlin example service sample:
package util.remoter.remoterclient
import android.app.Service
import android.content.Intent
import util.remoter.service.ISampleKotlinService_Stub
class SampleKotlinService : Service() {
private val binder by lazy {
ISampleKotlinService_Stub(KotlinServiceImpl())
}
override fun onBind(intent: Intent?) = binder
}
ISampleKotlinService_Stub
's constructor requires an instance of the IKotlinService
interface.
If I were to take your suggestion and make a marker interface that extends the java module interface, I would have to pass in a class that implements the marker interface, so it would have to be defined in an Android module along with the marker interface.
in other words, for your suggestion to work, your _Stub
class would need to be able to accept the base (IBusinessLogic
) interface/class, not just the (IAndroidInterface
) marker interface.
In your android module, create a simple implementation class for IAndroidInterface that extends from your actual implementation defined in the java module. Pass that to the stub
Then the java module class needs to be made open (since kotlin is closed by default) and I need to make this extension for every class I need and update constructors if the base class gets its constructor updated.
That is doable, but it is pretty tedious if you have to do it for a lot of classes, and this library is already trying to cut down on the tedious remoting code you would otherwise need to write.
After trying some of your suggestions, another issue I run into with this marker interface is that it cannot be made private or internal since the stub's constructor runs into this 'public' function exposes its 'internal' parameter type IAndroidInterface
so anyone who depends on the android module will now have that IAndroidInterface
interface show up in the API along with the base IBusinessLogic
and wonder why its public or if they need to care whether it is a remoter interface or not. it leaks implementation details.
Ok, I see your point. Let me think of what is the best way to do this. Will get back on this
Thanks so much. this is an excellent library and I appreciate the effort that you must have put in to writing it.
This is what i am thinking -- adding an optional parameter to the Remoter annotation so that you can specify whether the given interface is merely a delegate of another one and hence proxy and stub should be generated for the specified interface instead
So you would define the wrapper interface in your android module specifying a delegate to your java interface
@Remoter(delegateInterface = IBusinessLogic.class)
public interface IAndroidInterface extends IBusinessLogic {
}
will result in -
IBusinessLogic_Proxy and IBusinessLogic_Stub to get generated.
Generated IBusinessLogic_Proxy will extend IBusinessLogic
Generated IBusinessLogic_Stub will accept IBusinessLogic
You will still have to the wrapper IAndroidInterface defined in your android module where the annotation process dependency is defined.
sounds good?
It looks ok, but why would you have to have the interface extend the other if you are specifying it as a parameter to the annotation? does that add anything?
if not, I would remove that requirement and just have it be anything that can take an anotation.
with that requirement, if you leave that interface public (or even internal) you may confuse consumers as to which interface they should use, and would generally polute your API for no reason.
Also, could the parameter be an array of interfaces to generate remoter proxy/stubs for?
that way you define these in one location on one marker interface
perhaps something like the marker you have in your
suspender
library?@GenerateRemoterFor(classesToWrap = [ IBusinessLogic::class, IThirdPartyLibraryInterface::class ]) interface XXX
Is there any reason it can't be like it is in your suspender
library?
Agree, will do that way but use the same @ Remoter annotation itself. So you just would need one marker interface that specifies all other interfaces
Done, Try on version 2.0.4.
it might take some time for the version to be available at maven central.
odd, I get classpath issues now:
Supertypes of the following classes cannot be resolved.
Please make sure you have the required dependencies in the classpath:
class com.example.remoter.IBusinessLogic_Proxy, unresolved supertypes: remoter.RemoterProxy
Adding -Xextended-compiler-checks argument might provide additional information.
Do you have remoter-annotations added as dependnecy to your module?
Actually, yes. I had the pure base java/kotlin module depend on
implementation "com.josesamuel:remoter-annotations:2.0.4"
as well as the android module that depends on it.
But, I did find that changing the pure java/kotlin dependency to
api "com.josesamuel:remoter-annotations:2.0.4"
makes it work fine.
I have a multiplatform project (desktop and android) with a hierarchy of modules.
at the base is a plain Java library written in Kotlin. (
:businesslogic
) It contains an interface definition. (IBusinessLogic
)I then have an android library module that depends on this
.jar
, (:businesslogic:android
) where I need to create a remoter host service and a client for this interface.I can add
com.josesamuel:remoter-annotations
to the Java Library module (:businesslogic
) and annotate the interface, but since it is a pure java library with no Android dependency (it produces a.jar
, not an.aar
) I cannot addcom.josesamuel:remoter-builder
and have a remoterstub
orproxy
generated in that module.I would like to keep the interface defined in the Java module (
:businesslogic
) so as to have all the business logic separate from the android platform.would it be possible to add some kind of mechanism to have the
remoter-builder
generate an implementation for the interface (IBusinessLogic
) in the android module? (:businesslogic:android
) while keeping the interface in the java module? Perhaps this could apply to any interface, not just ones that are marked with@Remoter
?perhaps something like the marker you have in your
suspender
library?