Android Question android-serialport-api

jgbozza

Member
Licensed User
Longtime User
I'm using android-serialport-api library in my application in order to establish communication between one tablet as master and another devices connected over a RS485 network as slaves.
Recentely I had two tablets crashing after being turned on and coincidentaly both of them had faced troubles with power sources or cable malfunction before it happened.

Here below the logs of them:

--------- beginning of /dev/log/system


--------- beginning of /dev/log/main


** Activity (main) Create, isFirst = true **


** Activity (main) Resume **
java.lang.ExceptionInInitializerError


at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:234)
at java.lang.Class.forName(Class.java:181)
at anywheresoftware.b4a.shell.Shell.getCorrectClassName(Shell.java:378)
at anywheresoftware.b4a.shell.Shell.createObject(Shell.java:365)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:247)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:174)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:93)
at b4a.example.main.afterFirstLayout(main.java:91)
at b4a.example.main.access$100(main.java:16)
at b4a.example.main$WaitForLayout.run(main.java:76)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3688)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsatisfiedLinkError: Couldn't load serial_port: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:429)
at java.lang.System.loadLibrary(System.java:554)
at android_serialport_api.SerialPort.<clinit>(SerialPort.java:93)
... 22 more


AND THE OTHER ONE:

modulo485_process_globals (java line: 109)
java.lang.ExceptionInInitializerError
at jab.comboio.modulo485._process_globals(modulo485.java:109)
at jab.comboio.main.initializeProcessGlobals(main.java:703)
at jab.comboio.main.afterFirstLayout(main.java:94)
at jab.comboio.main.access$100(main.java:16)
at jab.comboio.main$WaitForLayout.run(main.java:76)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3688)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsatisfiedLinkError: Couldn't load serial_port: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:429)
at java.lang.System.loadLibrary(System.java:554)
at android_serialport_api.SerialPort.<clinit>(SerialPort.java:93)
... 14 more

Any ideas ????
 

jgbozza

Member
Licensed User
Longtime User
yes I did. I used it because I needed to set the baud rate programmaticaly and didnt find any way to do it with the builtin serial library
B4X:
#Region  Service Attributes 
    #StartAtBoot: false
#End Region

Sub Process_Globals
Try
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim Async As AsyncStreams
    Dim PORTA485 As SerialPort
    Dim RECEBIDO As String
Catch
    Msgbox(LastException.Message, "ERROR : SERIAL")
        Dim inten As Intent
        inten.Initialize(inten.ACTION_MAIN, "")
        inten.AddCategory("android.intent.category.MONKEY")
        inten.Flags = 0x10000000
        StartActivity(inten)
        ExitApplication   
End Try   
End Sub
Sub Service_Create
Try
    PORTA485.SetPort("/dev/ttymxc0",9600,0) 'THIS IS THE REASON WHY I USED THE android.serialport.api
    Async.Initialize(PORTA485.InputStream,PORTA485.OutputStream,"TESTE") 
    Do While Async.IsInitialized = False
    Loop
Catch 'in case of a general failure the last resort is to exit the application
        Msgbox(LastException.Message, "ERRO : SERIAL 0002")
        Dim inten As Intent
        inten.Initialize(inten.ACTION_MAIN, "")
        inten.AddCategory("android.intent.category.MONKEY")
        inten.Flags = 0x10000000
        StartActivity(inten)
        ExitApplication   
End Try
End Sub

Sub Service_Start (StartingIntent As Intent)
    Dim c As String
    c="ABCDEF"
    Async.Write(c.GetBytes("UTF8"))   
End Sub

Sub Service_Destroy

End Sub

Sub TESTE_NewData (Buffer() As Byte)
    .
    .
    .
    .
End Sub
 
Upvote 0

Ferraz71

Member
Licensed User
Longtime User
this is the code inside the eclipse...

B4X:
package android_serialport_api;

//import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io_OutputStream;
import android.util.Log;

import anywheresoftware.b4a.BA.ShortName;
@ShortName("SerialPort")

public class SerialPort {

    private static final String TAG = "SerialPort";

    /*
    * Do not remove or rename the field mFd: it is used by native method close();
    */
    private FileDescriptor mFd;
    private FileInputStream mFileInputStream;
    private FileOutputStream mFileOutputStream;

    public void SetPort (String path, int baudrate, int flags) throws SecurityException, IOException {

        mFd = open(path, baudrate, flags);
        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

    // Getters and setters
    public InputStream getInputStream() {
        return mFileInputStream;
    }

    public OutputStream getOutputStream() {
        return mFileOutputStream;
    }
  


    // JNI
    private native static FileDescriptor open(String path, int baudrate, int flags);
    public native void close();
    static {
        System.loadLibrary("serial_port");
    }
}
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Erel,

The code above posted by Ferraz71 is used to compile our serial library.

The thing about this error is that the app works perfectly for weeks, even months flawlessly and all of sudden when the tablet is turned on a error message is thrown. It never happens while the app is working, only when someone turns it on.

Fortunately I got to debug the error by connecting the tablet to the B4A IDE and the logs are posted up above in this thread. Both of them seemed to be similar (lib's not found) even if the erros don't seem to be exactly the same.

I saw a thread where someone had a similar issue and you recommended they to change the code from
B4X:
System.loadLibrary("serial_port");
to
B4X:
System.load(File.Combine(File.getDirInternal(), "serial_port.so"));
probably because the android system is losing the reference to the library path.

Thank you in advance.
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Yes, the problem happens in release mode. If I upload the application again from Basic 4 Android the problem vanishes. That's why this flaw has become so hard to be debugged.
As a workaround we are willing to check if the lib file exists before the application starts. If it doesnt means that somehow the path is lost or modified, then a internal routine copies this file from an external folder to the assets folder or where the application originally points to. Speaking of which, do you know where the app looks for a lib physically in the folders tree and how it can be accessed programmaticaly in order to avoid this error by doing that workaround procedure?
 
Last edited:
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Copying from the assets folder in startup will prevent the app from crashing ?
Yesterday one more error was thrown from another device and it has been working perfectly for almost 2 months.

What else could it be instead of file location ? Have you ever had a similar problem? Please let me know your thoughts.
 
Last edited:
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Erel, Do you think that this issue is related to a forced shut-down of the tablet? I asked the operators to hold the power off button in order to shut down the device after their shift. Another workaround should be putting a power off virtual button which would close all services and close the application afterwards. Is it possible to turn off the tablet programatically?

(For instance, there is another tablet with the same software but in a steady place. It's never been shut down and the exception never happened so far)
 
Last edited:
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Is there any example available? My feeling is that due to the forced closing of the device there is a chance of a file to get corrupted or to be allocated in a memory space that is no longer available once the tablet restarts the app after the forced shut down. Maybe we could stop the services to prevent it from happening.
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Erel,

My biggest issue is the customer getting stuck by the fact that the app wont close it when the exception is thrown. Is there a way to close the application remotelly from a desktop service the same way Basic4Android does? Would it be possible to send a Debugger Software to our client or staff only to debbug our application deployed to tablets? I mean, use the Basic4Android funcionallity but without the entire programming IDE.
 
Upvote 0
Top