Tim Coulter
Tim Coulter

Reputation: 8927

Xamarin.Android Java bindings library runtime failure accessing native library

TL;DR: I am looking for a way to find and extract a native shared library (.so) file from an Android device that is running a vendor-specific custom Android build. I need this file as the missing piece in a Xamarin.Android Java bindings library.

I am attempting to create a Xamarin.Android bindings library for a Java SDK that exposes laser barcode scanning APIs on Famoco's Android devices. These devices run a vendor-specific Android build, which supports some special features, such as centralized device management.

I followed the usual procedures to create the bindings library, without using any custom transforms or additions, and there were no compiler errors.

Here is the factory method, generated within the bindings library, that attempts to create a new BarCodeReader instance:

[Register ("open", "(ILandroid/content/Context;)Lcom/zebra/adc/decoder/BarCodeReader;", "")]
public static unsafe global::Com.Zebra.Adc.Decoder.BarCodeReader Open (int readerId, global::Android.Content.Context context)
{
    const string __id = "open.(ILandroid/content/Context;)Lcom/zebra/adc/decoder/BarCodeReader;";
    try {
        JniArgumentValue* __args = stackalloc JniArgumentValue [2];
        __args [0] = new JniArgumentValue (readerId);
        __args [1] = new JniArgumentValue ((context == null) ? IntPtr.Zero : ((global::Java.Lang.Object) context).Handle);
        var __rm = _members.StaticMethods.InvokeObjectMethod (__id, __args);
        return global::Java.Lang.Object.GetObject<global::Com.Zebra.Adc.Decoder.BarCodeReader> (__rm.Handle, JniHandleOwnership.TransferLocalRef);
    } finally {
    }
}

The above code fails while executing the following line:

var __rm = _members.StaticMethods.InvokeObjectMethod (__id, __args);

An exception is thrown: No implementation found for void com.zebra.adc.decoder.BarCodeReader.native_setup(java.lang.Object, int, java.lang.Object).

I learned from the troubleshooting guidelines that this type of failure is typically caused by the inability to resolve a required native library.

In an attempt to confirm this as the cause, I used JD-GUI to decompile the Famoco JAR, from which I extracted the following snippets of the implementation code:

// This is the underlying Java implementation of the above bindings library factory method
public static BarCodeReader open(int readerId, Context context)
{
    return new BarCodeReader(readerId, context);
}

// This is the BarCodeReader constructor that is called by the factory method
BarCodeReader(int readerId, Context context)
{
    this.mEventHandler = null;
    this.mAutoFocusCallback = null;
    this.mDecodeCallback = null;
    this.mErrorCallback = null;
    this.mPreviewCallback = null;
    this.mSnapshotCallback = null;
    this.mVideoCallback = null;
    this.mZoomListener = null;

    Looper aLooper = Looper.myLooper();
    if (null == aLooper) {
        aLooper = Looper.getMainLooper();
    }
    if (aLooper != null) {
        this.mEventHandler = new EventHandler(this, aLooper);
    }
    native_setup(new WeakReference(this), readerId, context);
}

// This method is called by the above constructor, but fails because no implementation exists
private final native void native_setup(Object paramObject, int paramInt);

It seems to me that the above runtime error is occurring because the private method native_setup is not implemented within the Java code, but separately within a native library that is not referenced anywhere within my bindings library project. Does this seem like a reasonable diagnosis?

Unfortunately, I didn't find any .so (native library) files within the SDK kit supplied by Famoco. I have contacted their support team, who stated that it is not necessary to link an .so file when consuming their SDK JAR. Famoco are not keen to support cross-platform apps on their devices, but they did confirm that they have other customers using Xamarin, who appear to have solved this problem. Unfortunately, Famoco support don't seem able to tell me how to achieve this.

Could it be that the required native library already exists on the device (deployed as part of the custom Android build)? To verify this hypothesis, I installed the Famoco sample laser scanning app, which runs correctly, even though there is no sign of a .so file within its project source kit.

If so, is it feasible to find and extract the .so file from the Android environment and how should I do this?

Upvotes: 1

Views: 357

Answers (1)

Alex Cohn
Alex Cohn

Reputation: 57163

Yes, the libbarcodereader44.so file should be preinstalled on the custom device. It may be either in the /system/lib or in the /vendor/lib directory. You must load this library from your code before calling the open () method. Here you can find more details about the Famoco SDK.

Upvotes: 1

Related Questions