masesgroup / masesgroup/JNet

Defining `android.os.RemoteCallbackList$Builder$InterfaceDiedCallback` as listener class, JNetReflector is not able to reflect it in the right way.

Open
#749 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug JNetReflector
Dominant language
C#
Stars
44
Forks
4
Avg merge
17h 38m
Merged PRs (30d)
78

Description

Defining android.os.RemoteCallbackList$Builder$InterfaceDiedCallback as listener class, JNetReflector is not able to reflect it in the right way.

  • Java:
    • the output generated from JNetReflector is the following:
package org.mases.netdroid.generated.android.os;

public final class RemoteCallbackList_Builder_InterfaceDiedCallback implements org.mases.jcobridge.IJCListener, android.os.RemoteCallbackList.Builder.InterfaceDiedCallback {
    final org.mases.jcobridge.JCListener _internalListener;

    public RemoteCallbackList_Builder_InterfaceDiedCallback(String key) throws org.mases.jcobridge.JCNativeException {
        super();
        _internalListener = new org.mases.jcobridge.JCListener(key);
    }

    public synchronized void release() {
       _internalListener.release();
    }
    
    public synchronized void raiseEvent(String eventName) {
       _internalListener.raiseEvent(eventName);
    }
    
    public synchronized void raiseEvent(String eventName, Object e) {
       _internalListener.raiseEvent(eventName, e);
    }
    
    public synchronized void raiseEvent(String eventName, Object e, Object... objects) {
       _internalListener.raiseEvent(eventName, e, objects);
    }
    
    public Object getEventData() {
       return _internalListener.getEventData();
    }
    
    public boolean hasExtraData() {
       return _internalListener.hasExtraData();
    }
    
    public int extraDataLength() {
       return _internalListener.extraDataLength();
    }
    
    public Object[] extraData() {
       return _internalListener.extraData();
    }
    
    public Object getReturnData() {
       return _internalListener.getReturnData();
    }
    
    public void setReturnData(Object retData) {
       _internalListener.setReturnData(retData);
    }

    //@Override
    public void onInterfaceDied(android.os.RemoteCallbackList arg0, java.lang.Object arg1, java.lang.Object arg2) {
        org.mases.jnet.developed.JNetEventResult eventDataExchange = new org.mases.jnet.developed.JNetEventResult();
        raiseEvent("onInterfaceDied", eventDataExchange, arg0, arg1, arg2); if (!eventDataExchange.getHasOverride()) throw new UnsupportedOperationException("The method shall be implemented in .NET side since does not have a default implementation within the JVM");
    }

}

  • however the compiler reports:
Error:  /home/runner/work/netdroid/netdroid/src/jvm/netdroid/src/main/java/org/mases/netdroid/generated/android/os/RemoteCallbackList_Builder_InterfaceDiedCallback.java:[25,14] org.mases.netdroid.generated.android.os.RemoteCallbackList_Builder_InterfaceDiedCallback is not abstract and does not override abstract method onInterfaceDied(android.os.RemoteCallbackList,android.os.IInterface,java.lang.Object) in android.os.RemoteCallbackList.Builder.InterfaceDiedCallback

  • manually updating the class, the implementation which avoid compilation errors is the following:

package org.mases.netdroid.generated.android.os;

public final class RemoteCallbackList_Builder_InterfaceDiedCallback<E extends android.os.IInterface> implements org.mases.jcobridge.IJCListener, android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E extends android.os.IInterface> {
    final org.mases.jcobridge.JCListener _internalListener;

    public RemoteCallbackList_Builder_InterfaceDiedCallback(String key) throws org.mases.jcobridge.JCNativeException {
        super();
        _internalListener = new org.mases.jcobridge.JCListener(key);
    }

    public synchronized void release() {
       _internalListener.release();
    }
    
    public synchronized void raiseEvent(String eventName) {
       _internalListener.raiseEvent(eventName);
    }
    
    public synchronized void raiseEvent(String eventName, Object e) {
       _internalListener.raiseEvent(eventName, e);
    }
    
    public synchronized void raiseEvent(String eventName, Object e, Object... objects) {
       _internalListener.raiseEvent(eventName, e, objects);
    }
    
    public Object getEventData() {
       return _internalListener.getEventData();
    }
    
    public boolean hasExtraData() {
       return _internalListener.hasExtraData();
    }
    
    public int extraDataLength() {
       return _internalListener.extraDataLength();
    }
    
    public Object[] extraData() {
       return _internalListener.extraData();
    }
    
    public Object getReturnData() {
       return _internalListener.getReturnData();
    }
    
    public void setReturnData(Object retData) {
       _internalListener.setReturnData(retData);
    }

    @Override
    public void onInterfaceDied(android.os.RemoteCallbackList<E> arg0, E arg1, java.lang.Object arg2) {
        org.mases.jnet.developed.JNetEventResult eventDataExchange = new org.mases.jnet.developed.JNetEventResult();
        raiseEvent("onInterfaceDied", eventDataExchange, arg0, arg1, arg2); if (!eventDataExchange.getHasOverride()) throw new UnsupportedOperationException("The method shall be implemented in .NET side since does not have a default implementation within the JVM");
    }

}

  • .NET
    • the implementation of the listener seems to conform to the expectation
    • however the following method, or other one, does not define the parameter in the right way:
                /// <summary>
                /// <see href="https://developer.android.com/reference/android/os/RemoteCallbackList.Builder.InterfaceDiedCallback.html#onInterfaceDied(android.os.RemoteCallbackList,android.os.IInterface,java.lang.Object)"/>
                /// </summary>
                /// <param name="arg0"><see cref="Android.Os.RemoteCallbackList"/></param>
                /// <param name="arg1"><typeparamref name="E"/></param>
                /// <param name="arg2"><see cref="object"/></param>
                public virtual void OnInterfaceDied(Android.Os.RemoteCallbackList<E> arg0, E arg1, object arg2)
                {
                    hasOverrideOnInterfaceDied = false;
                }
  • the error is: The type 'E' cannot be used as type parameter 'E' in the generic type or method 'RemoteCallbackList<E>'. There is no boxing conversion or type parameter conversion from 'E' to 'Android.Os.IIInterface'.

The class generation of JNetReflector shall be reviewed when this conditions are encountered, an issue will be opened on JNet.

Originally posted by @masesdevelopers in https://github.com/masesgroup/netdroid/issues/181#issuecomment-3334312620

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at JNetReflector's class generation for android.os.RemoteCallbackList.Builder.InterfaceDiedCallback and compare the generated Java class with the Android generic signature shown in the issue. Also inspect the generated C# OnInterfaceDied method and verify the generic constraint; done means both generated outputs compile without the reported errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, java
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.