Java Question Library and JniWrapper

Wal

Member
Licensed User
Longtime User
I have made a Library with the Ndk and a Wrapper. The wrapper works with Eclipse, how can I use it at B4A?

Wrapper:
B4X:
#include <jni.h>
#include "./library/test.h"

extern "C" {
    JNIEXPORT jboolean JNICALL Java_de_wal_librarytest_MBJniClass_OpenPort(JNIEnv * env, jobject obj, jboolean usebool);
    JNIEXPORT jboolean JNICALL Java_de_wal_librarytest_MBJniClass_ClosePort(JNIEnv * env, jobject obj);
};

JNIEXPORT jboolean JNICALL Java_de_wal_librarytest_MBJniClass_OpenPort(JNIEnv * env, jobject obj, jboolean usebool)
{
    return OpenPort(usebool);
}

JNIEXPORT jboolean JNICALL Java_de_wal_librarytest_MBJniClass_ClosePort(JNIEnv * env, jobject obj)
{
    return ClosePort();
}

Class:
B4X:
package de.wal.librarytest;

public class MBJniClass {
      static {
         System.loadLibrary("testlibrary");
      }
     
      public static native boolean OpenPort(boolean usebool);
      public static native boolean ClosePort();
}

Eclipse-Example:
B4X:
package de.wal.librarytest;

import de.wal.librarytest.MBJniClass;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        if (MBJniClass.OpenPort(true)) {
           int i = 1    
       }
    }
 

DonManfred

Expert
Licensed User
Longtime User
You need to wrote a wrapper which can be used in b4a.

Something like

B4X:
import de.wal.MBJniClass;
import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA.Author;

@Version(1.00f)
@Author("...")
@ShortName("MBJni")
//@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
//@Events(values={"onSigned(sign As Object)"})
//@DependsOn(values={"android-viewbadger"})
public class MBJniClassWrapper extends AbsObjectWrapper<MBJniClass> {
    private BA ba;
    private String eventName;
    public void Initialize(final BA ba, String EventName) {
        _initialize(ba, null, EventName);
    }
   
    @Hide
    public void _initialize(final BA ba, Object activityClass, String EventName) {
        this.eventName = EventName.toLowerCase(BA.cul);
        this.ba = ba;
        this.setObject(new MBJniClass());
     }
   
    public void ClosePort(){
        this.getObject().ClosePort();
    }
   
    public void ClosePort(boolean usebool){
        this.getObject().OpenPort(usebool);
    }
}
 
  • Like
Reactions: Wal

MaFu

Well-Known Member
Licensed User
Longtime User
If you use the library only with B4A then you can create the JNI wrapper itself B4A compatible (as in Don Manfreds example), in this case there is no need to create a wrapper for the wrapper.
 
  • Like
Reactions: Wal

Wal

Member
Licensed User
Longtime User
it works, thank you
 

Wal

Member
Licensed User
Longtime User
I have a problem with a call. What should be the Jniexport ?

C++ Code:
B4X:
char GetError(int *err)
{   
    DWORD dwBytes;
    unsigned char input[10]={0};
   
    if(!ReadSerialBytes(hSerial, input, 10,&dwBytes,true))
        return -1;

    if(dwBytes < 8)
        return -1;
       
    if(Header(input,dwBytes))
    {
        if (input[5]==0x01)
        {
            *err=0;
            return input[6];
        }
       
        if (input[5]==0x03)
        {
            if (input[6]>0)
            {
                *err=(0xFF & input[7]) << 8 |(0xFF & input[8]);       
                return 1;
            }
            else
                return 0;
        }
       
        return -1;
    }
    else
        return -1;
}

Jni :
B4X:
JNIEXPORT jbyte JNICALL Java_de_wal_library_MBLib_GetError(JNIEnv * env, jobject obj, jint err)
{
    return GetError(&err);
}
not correct
 

Wal

Member
Licensed User
Longtime User
No error message, err is always 0 and not 66.
input[6] is the correct.

For testing, I use this code:
B4X:
if (input[5]==0x01)
        {
            *err=66;
            return input[6];
        }
 

Wal

Member
Licensed User
Longtime User
Declare:
B4X:
_extern char GetError(int *err);
 

Informatix

Expert
Licensed User
Longtime User
I have a problem with a call. What should be the Jniexport ?

C++ Code:
B4X:
char GetError(int *err)
{  
    DWORD dwBytes;
    unsigned char input[10]={0};
  
    if(!ReadSerialBytes(hSerial, input, 10,&dwBytes,true))
        return -1;

    if(dwBytes < 8)
        return -1;
      
    if(Header(input,dwBytes))
    {
        if (input[5]==0x01)
        {
            *err=0;
            return input[6];
        }
      
        if (input[5]==0x03)
        {
            if (input[6]>0)
            {
                *err=(0xFF & input[7]) << 8 |(0xFF & input[8]);      
                return 1;
            }
            else
                return 0;
        }
      
        return -1;
    }
    else
        return -1;
}

Jni :
B4X:
JNIEXPORT jbyte JNICALL Java_de_wal_library_MBLib_GetError(JNIEnv * env, jobject obj, jint err)
{
    return GetError(&err);
}
not correct
When you export something to Java, it must be a JNI type or object. jchar is the JNI type corresponding to char.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
 

Wal

Member
Licensed User
Longtime User

Wal

Member
Licensed User
Longtime User
Ok,
i have rewrite the Jni:
B4X:
JNIEXPORT jintArray JNICALL Java_de_wal_library_MBLib_GetError(JNIEnv * env, jobject obj)
{
    jint value[2] = {};
    jint err;
    jintArray arr = env->NewIntArray(2);
    value[0] = GetError(&err);
    value[1] = err;
    env->SetIntArrayRegion(arr, 0, 2, value);
    return arr;
}

How should I declare the wrapper in B4A ?
B4X:
package de.wal.library;

import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA.Author;

@Version(1.00f)
@Author("Ich")
@ShortName("MBLib")

public class MBLib {
      static {
         System.loadLibrary("mblibrary");
      }
      public static native long CommVersion();
      public static native boolean OpenPort(String port, boolean usebool);
      public static native boolean ClosePort();
      public static native ????? GetError();
}
 

Wal

Member
Licensed User
Longtime User
The solution is:
B4X:
public static native int[] GetError();
B4A:
B4X:
Dim Err(1) As Int
    Err = MB.GetError
    labErr.Text = Err(0)
    labValue.Text = Err(1)

Thank's
 

Wal

Member
Licensed User
Longtime User
Next problem, how can I generate a Unicode string from a array of int.
Jni:
B4X:
public static native int[] GetProgramName();

B4A:
B4X:
Dim ProgramName(400) As Int

ProgramName = MB.GetProgramName

labProgamName.Text = ?????
 
Top