Problem with Java.Object


#1

Hello,
I am trying to integrate an Android SMS Catcher Library into my Fuse App using Uno. I keep getting the error below:

Compiling syntax tree
SmsCatcher\SmsCatcher.uno(19.10): E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(19,11): Error E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?SmsCatcher\SmsCatcher.uno(19.10): E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(19,11): Error E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?0.48 s

from this line

Java.Object _smsCatcher;

If I change that line to

object _smsCatcher;

then the lines below

        this.AddMember(new NativeFunction("Start", (NativeCallback)Start));
        this.AddMember(new NativeFunction("Stop", (NativeCallback)Stop));

gives the following error

Compiling syntax tree
SmsCatcher\SmsCatcher.uno(36.68): E2029: '<method_group>' has no defined cast to type Fuse.Scripting.NativeCallback
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(36,69): Error E2029: '<method_group>' has no defined cast to type Fuse.Scripting.NativeCallbackSmsCatcher\SmsCatcher.uno(37.67): E2029: '<method_group>' has no defined cast to type Fuse.Scripting.NativeCallback
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(37,68): Error E2029: '<method_group>' has no defined cast to type Fuse.Scripting.NativeCallback0.98 s

Here is the full source code

using Uno;
using Fuse;
using Uno.UX;
using Android;
using Fuse.Platform;
using Fuse.Reactive;
using Fuse.Scripting;
using Uno.Threading;
using Uno.Permissions;
using Uno.Compiler.ExportTargetInterop;

[extern(Android) ForeignInclude(Language.Java, "android.content.Intent")]
[extern(Android) ForeignInclude(Language.Java, "android.util.Log")]
[extern(Android) ForeignInclude(Language.Java, "com.goldenseed.smscatcher.*")]
[extern(Android) ForeignInclude(Language.Java, "com.fuse.Activity")]
[UXGlobalModule]
public class SmsCatcher : NativeEventEmitterModule
{
    Java.Object _smsCatcher; // <====== PROBLEM LINE
    static readonly SmsCatcher _instance;
    static readonly string PLATFORM_NOT_SUPPORTED = "Non Android Platforms are not Supported";

    public SmsCatcher() : base(true, "SMSRECEIVED", "SMSERROR", "PermissionReceived", "PermissionDenied")
    {
        if defined(Android)
        {
            Permissions.Request(Permissions.Android.INTERNET).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.READ_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.RECEIVE_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
        }

        if (_instance != null) return;

	_instance = this;
	Uno.UX.Resource.SetGlobalKey(_instance, "SmsCatcher");
        this.AddMember(new NativeFunction("Start", (NativeCallback)Start));// <====== PROBLEM LINE
        this.AddMember(new NativeFunction("Stop", (NativeCallback)Stop));// <====== PROBLEM LINE
    }

    extern(Android) void Start(Fuse.Scripting.Context c, object[] args)
    {
		if (this._smsCatcher == null) {
            this.Init();
        }

        if (args.Length > 0){
            if (args[0] != null){
                var phoneNumberFilter = (string)args[0];
                this.SetPhoneNumberFilter(phoneNumberFilter);
            }

            if (args.Length > 1){
                if (args[1] != null){
                    var regexFilter = (string)args[1];
                    this.SetRegexFilter(regexFilter);
                }
            }
        }

        this.StartSmsCatcher();
    }
    extern(!Android) void Start(Fuse.Scripting.Context c, object[] args)
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
    }

    extern(Android) void Stop()
    {
        if (this._smsCatcher != null) {
            this.StopSmsCatcher();
        }
    }
    extern(!Android) void Stop()
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
    }

    public void onSmsMessage(string smsMessage)
    {
        this.Emit("SMSRECEIVED", smsMessage);
    }

    extern(Android) void OnPermissionsPermitted(PlatformPermission p)
    {
        this.Emit("PermissionReceived", "Permissions allowed" + p);
    }

    extern(Android) void OnPermissionsRejected(Exception e)
    {
        this.Emit("PermissionDenied", "PermissionDenied "+ e);
    }


    [Foreign(Language.Java)]
    extern(Android) void StartSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStart();
    @}

    [Foreign(Language.Java)]
    extern(Android) void StopSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStop();

    @}

    [Foreign(Language.Java)]
    extern(Android) void SetRegexFilter(string regexFiler)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setFilter(regexFiler);
    @}

    [Foreign(Language.Java)]
    extern(Android) void SetPhoneNumberFilter(string phoneNumber)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setPhoneNumberFilter(phoneNumber);
    @}

    [Foreign(Language.Java)]
    extern(Android) void Init()
    @{
        AndroidSmsCatcher smsCatcher = new AndroidSmsCatcher(Activity.getRootActivity(), new OnSmsCatchListener<String>() {
            @Override
            public void onSmsCatch(String message) {
                 @{SmsCatcher:Of(_this).onSmsMessage(string):Call(message)};
            }
        });

        @{SmsCatcher:Of(_this)._smsCatcher:Set(smsCatcher)};
    @}
}

The java source files are bundled with the project
I have tried uno clean but no luck
What am I doing wrong? I have been on this for 2 days.
I am new to Fuse but experienced in C#;


#2

Your AddMember() lines are fine. And looking for Java.Object while in Uno doesn’t seem right, you still need to work with Uno-types.

The problem is that the callback functions do not match the signature of a NativeCallback.

It’s the actual callback methods that need to return an object, and accept the right arguments. Fixed your code so that it compiles for me without any errors (but didn’t test if it actually does anything):

using Uno;
using Fuse;
using Uno.UX;
using Android;
using Fuse.Platform;
using Fuse.Reactive;
using Fuse.Scripting;
using Uno.Threading;
using Uno.Permissions;
using Uno.Compiler.ExportTargetInterop;

[extern(Android) ForeignInclude(Language.Java, "android.content.Intent")]
[extern(Android) ForeignInclude(Language.Java, "android.util.Log")]
[extern(Android) ForeignInclude(Language.Java, "com.goldenseed.smscatcher.*")]
[extern(Android) ForeignInclude(Language.Java, "com.fuse.Activity")]
[UXGlobalModule]
public class SmsCatcher : NativeEventEmitterModule
{
    object _smsCatcher; // <====== PROBLEM LINE
    static readonly SmsCatcher _instance;
    static readonly string PLATFORM_NOT_SUPPORTED = "Non Android Platforms are not Supported";

    public SmsCatcher() : base(true, "SMSRECEIVED", "SMSERROR", "PermissionReceived", "PermissionDenied")
    {
        if defined(Android)
        {
            Permissions.Request(Permissions.Android.INTERNET).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.READ_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.RECEIVE_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
        }

        if (_instance != null) return;

    _instance = this;
    Uno.UX.Resource.SetGlobalKey(_instance, "SmsCatcher");
        this.AddMember(new NativeFunction("Start", (NativeCallback)Start));// <====== PROBLEM LINE
        this.AddMember(new NativeFunction("Stop", (NativeCallback)Stop));// <====== PROBLEM LINE
    }

    extern(Android) object Start(Fuse.Scripting.Context c, object[] args)
    {
        if (this._smsCatcher == null) {
            this.Init();
        }

        if (args.Length > 0){
            if (args[0] != null){
                var phoneNumberFilter = (string)args[0];
                this.SetPhoneNumberFilter(phoneNumberFilter);
            }

            if (args.Length > 1){
                if (args[1] != null){
                    var regexFilter = (string)args[1];
                    this.SetRegexFilter(regexFilter);
                }
            }
        }

        this.StartSmsCatcher();

        return null;
    }
    extern(!Android) object Start(Fuse.Scripting.Context c, object[] args)
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
        return null;
    }

    extern(Android) object Stop(Fuse.Scripting.Context c, object[] args)
    {
        if (this._smsCatcher != null) {
            this.StopSmsCatcher();
        }
        return null;
    }
    extern(!Android) object Stop(Fuse.Scripting.Context c, object[] args)
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
        return null;
    }

    public void onSmsMessage(string smsMessage)
    {
        this.Emit("SMSRECEIVED", smsMessage);
    }

    extern(Android) void OnPermissionsPermitted(PlatformPermission p)
    {
        this.Emit("PermissionReceived", "Permissions allowed" + p);
    }

    extern(Android) void OnPermissionsRejected(Exception e)
    {
        this.Emit("PermissionDenied", "PermissionDenied "+ e);
    }


    [Foreign(Language.Java)]
    extern(Android) void StartSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStart();
    @}

    [Foreign(Language.Java)]
    extern(Android) void StopSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStop();

    @}

    [Foreign(Language.Java)]
    extern(Android) void SetRegexFilter(string regexFiler)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setFilter(regexFiler);
    @}

    [Foreign(Language.Java)]
    extern(Android) void SetPhoneNumberFilter(string phoneNumber)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setPhoneNumberFilter(phoneNumber);
    @}

    [Foreign(Language.Java)]
    extern(Android) void Init()
    @{
        AndroidSmsCatcher smsCatcher = new AndroidSmsCatcher(Activity.getRootActivity(), new OnSmsCatchListener<String>() {
            @Override
            public void onSmsCatch(String message) {
                 @{SmsCatcher:Of(_this).onSmsMessage(string):Call(message)};
            }
        });

        @{SmsCatcher:Of(_this)._smsCatcher:Set(smsCatcher)};
    @}
}

#3

Thanks for the Fast Response. Does your fix take care of the Java.Object problem?
I will Test your fix and get back to you.
Thanks


#4

Yeah, it does fix the Java.Object problem, since there is no reference to Java.Object any more.

As I said above, I fixed the code so that it compiles without any errors, but I didn’t test if it does what it’s supposed to do. That’s on you.


#5

My problem with AddMember() is fixed now, but I still have issues with this code

Java.Object _smsCatcher;

_smsCatcher is a variable in Uno that I want store a native Java Object in so I can use later when I need to call a method on it but I keep getting compile error

Compiling syntax tree
SmsCatcher\SmsCatcher.uno(19.10): E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(19,11): Error E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?SmsCatcher\SmsCatcher.uno(19.10): E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?
D:\PROJECTS\MOBILE\FUSE\HikerPlay\SmsCatcher\SmsCatcher.uno(19,11): Error E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?0.41 s

From Fuse Docs,

[So what happens when we want to return a Java or Objective-C object from a foreign method? The answer is that we get an opaque object representing the foreign object.

An Objective-C object (id) is an ObjC.Object and a Java object (Object) is a ```Java.Object`` in Uno."]

I am on Fuse 1.6.1, it appears Java.Object does not exist in my setup, but I have compiled and previewed sample projects that make use of ```Java.Object`` successfully.

In what Uno namespace do I find ObjC.Object and ```Java.Object``?

How do I store a return value from a Java Foreign method in Uno?


#6

Oh, I see your point now.

Java.Object is only available to code running on Android target, while ObjC.Object is when you’re on iOS. You can take a look at one of these libraries since many of them use both.

For example, take a look at this line. Note the use of extern(Android) in the method signature - meaning, this code gets compiled for Android.


#7

Your last reply was the MAGIC WAND I needed to move forward. What I eventually did was to create two classes, one for Android and another one for other platforms as shown below:

[UXGlobalModule]
extern(!Android) public class SmsCatcher : NativeEventEmitterModule
{
    static readonly string PLATFORM_NOT_SUPPORTED = "Non Android Platforms are not Supported";

    public SmsCatcher() : base(true, "SMSRECEIVED", "SMSERROR", "PermissionReceived", "PermissionDenied")
    {
        this.AddMember(new NativeFunction("Start", (NativeCallback)Start));
        this.AddMember(new NativeFunction("Stop", (NativeCallback)Stop));
    }

    extern(!Android) object Start(Fuse.Scripting.Context c, object[] args)
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
        return null;
    }

    extern(!Android) object Stop(Fuse.Scripting.Context c, object[] args)
    {
        debug_log PLATFORM_NOT_SUPPORTED;
        this.Emit("SMSERROR", PLATFORM_NOT_SUPPORTED);
        return null;
    }
}

AND

[extern(Android) ForeignInclude(Language.Java, "android.content.Intent")]
[extern(Android) ForeignInclude(Language.Java, "android.util.Log")]
[extern(Android) ForeignInclude(Language.Java, "com.goldenseed.smscatcher.*")]
[extern(Android) ForeignInclude(Language.Java, "com.fuse.Activity")]
[UXGlobalModule]
extern(Android) public class SmsCatcher : NativeEventEmitterModule
{
    Java.Object _smsCatcher;
    static readonly SmsCatcher _instance;

    public SmsCatcher() : base(true, "SMSRECEIVED", "SMSERROR", "PermissionReceived", "PermissionDenied")
    {
        if defined(Android)
        {
            Permissions.Request(Permissions.Android.INTERNET).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.READ_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
            Permissions.Request(Permissions.Android.RECEIVE_SMS).Then(OnPermissionsPermitted,OnPermissionsRejected);
        }

        if (_instance != null) return;

	_instance = this;
	Uno.UX.Resource.SetGlobalKey(_instance, "SmsCatcher");
        this.AddMember(new NativeFunction("Start", (NativeCallback)Start));
        this.AddMember(new NativeFunction("Stop", (NativeCallback)Stop));
    }

    extern(Android) object Start(Fuse.Scripting.Context c, object[] args)
    {
        if (this._smsCatcher == null) {
            this.Init();
        }

        if (args.Length > 0){
            if (args[0] != null){
                var phoneNumberFilter = (string)args[0];
                this.SetPhoneNumberFilter(phoneNumberFilter);
            }

            if (args.Length > 1){
                if (args[1] != null){
                    var regexFilter = (string)args[1];
                    this.SetRegexFilter(regexFilter);
                }
            }
        }

        this.StartSmsCatcher();

        return null;
    }

    extern(Android) object Stop(Fuse.Scripting.Context c, object[] args)
    {
        if (this._smsCatcher != null) {
            this.StopSmsCatcher();
        }
        return null;
    }

    public void onSmsMessage(string smsMessage)
    {
        this.Emit("SMSRECEIVED", smsMessage);
    }

    extern(Android) void OnPermissionsPermitted(PlatformPermission p)
    {
        this.Emit("PermissionReceived", "Permissions allowed" + p);
    }

    extern(Android) void OnPermissionsRejected(Exception e)
    {
        this.Emit("PermissionDenied", "PermissionDenied "+ e);
    }

    [Foreign(Language.Java)]
    extern(Android) void StartSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStart();
    @}

    [Foreign(Language.Java)]
    extern(Android) void StopSmsCatcher()
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.onStop();

    @}

    [Foreign(Language.Java)]
    extern(Android) void SetRegexFilter(string regexFiler)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setFilter(regexFiler);
    @}

    [Foreign(Language.Java)]
    extern(Android) void SetPhoneNumberFilter(string phoneNumber)
    @{
        AndroidSmsCatcher smsCatcher = (AndroidSmsCatcher)@{SmsCatcher:Of(_this)._smsCatcher:Get()};
        smsCatcher.setPhoneNumberFilter(phoneNumber);
    @}

    [Foreign(Language.Java)]
    extern(Android) void Init()
    @{
        AndroidSmsCatcher smsCatcher = new AndroidSmsCatcher(Activity.getRootActivity(), new OnSmsCatchListener<String>() {
            @Override
            public void onSmsCatch(String message) {
                 @{SmsCatcher:Of(_this).onSmsMessage(string):Call(message)};
            }
        });

        @{SmsCatcher:Of(_this)._smsCatcher:Set(smsCatcher)};
    @}
}

Now my project compiles with no errors. I only need to test on a real android device

Thanks @Uldis for your patience;

I am amazed at the creativity that goes into creating a Mobile Platform like Fuse. Having done WPF and Silverlight from Microsoft, I feel like I am on familiar grounds and that this is WPF made perfect.


#8

Wonderful! It’s great you got it working. The approach with native modules in Fuse is usually exactly that: writing 3 different implementations for the actual functionality targeting each platform (local preview, Android and iOS), and having a common base class that serves as a single entry-point.

Thanks for the kind words :slight_smile:


#9

@Uldis I tested it on my Android device and it worked. I will be sharing the full code with the community in the coming days.

I think the Docs should be updated to point out that Java.Object is only available to code running on Android target, while ObjC.Object is only available when you’re on iOS.

The take away for me is to always partition your Foreign code using extern() to target your platform of choice while providing dummy implementation for platforms you don’t intend to support

Thanks a lot.


#10

I came across the same issue, the compiler kept throwing this error:
E3111: 'Java' does not contain type or namespace 'Object'. Could you be missing a package reference?

Thanks guys!

I added:

using Android;

and made sure to use extern(Android) for functions that may include a Java object, even if the Uno function isn’t written with the Java language but includes a Java object (in my case type Java.Object) as input from a function call inside a function using Java.