Java Question Help with B4A Library

walterf25

Expert
Licensed User
Longtime User
Hello All, i'm writing a library for some tablets that have IR BarCode Sanners integrated. I have received some code examples from the manufacturer, i have one of them working, but i'm having a problem with the second tablet.

I can get the IR Scanner to light up but when i try to scan a barcode I get this error.

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.app.Dialog.<init>(Dialog.java:107)
at android.app.AlertDialog.<init>(AlertDialog.java:114)
at android.app.AlertDialog$Builder.create(AlertDialog.java:913)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:206)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
at com.genesis.irscanner.IRScanner$2$1.run(IRScanner.java:123)
at java.util.Timer$TimerImpl.run(Timer.java:284)
** Activity (main) Pause, UserClosed = true **
[/QUOTE]

this happens when I try to display the results from the barcode scanned in an edittext box, If i just log the results it works fine and i can see the results in the unfiltered logs, it is only when i add the code to display the results in the edittext that this happens.

This is the code I have written in Eclipse, if anyone here has any idea on how to fix this issue I will really appreciate it.

B4X:
package com.genesis.irscanner;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.streams.File;

import android.os.Handler;
import android.os.Message;
import android.port.SerialPortAdapter;
import android.port.SerialPortManager;
import android.util.Log;
import android.widget.Toast;

import com.android.gpio.UartIo;



@ShortName("IRScanner")
@ActivityObject
@Version(1f)
@Author("Walter")
@Events(values={"error (error as string)", "results"})
@DependsOn(values = { "androidext" })

public class IRScanner extends Activity{
   
   private final String PORT_NAME = "/dev/ttyS0";
   private ArrayList<String> mResults;
   private UartIo mEnable;
   private boolean mCanExit;
   private Timer mTimer;
   private TimerTask mTask;
   private final int MSG_UPDATE = 100;
   private Timer mExtiTimer;
   private TimerTask mExitTask;
   private ArrayList<byte[]> mReadBuffer;
   private boolean mIsRunning = false;;
   private BA myba;
   private String eventname;
   private final SerialPortAdapter mSerialport = SerialPortManager.getAdapter(PORT_NAME, 115200);;

public void Initialize(BA ba, String EventName){
   myba = ba;
   mEnable = new UartIo();
   mReadBuffer = new ArrayList<byte[]>();
   mEnable.setTxState(true);
   mSerialport.open();
   mIsRunning = true;
   mReadThread.start();
   final String eventName = EventName.toLowerCase(BA.cul);
   eventname = eventName;
   //updateResult();
}

private Handler mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
      myba.raiseEvent(myba.context, eventname + "_received", msg.toString());
      switch (msg.what) {
      case MSG_UPDATE:
         if (mResults.size() >= 999) {
            //String title = getResources().getString(R.string.overflow);
            //String show = title + "\r\n" + (String)msg.obj;
            //showToast(show, Toast.LENGTH_SHORT);
            //mErrPlayer.start();
            //Log.d("error", "Error Ocurred!");
         } else {
            //mResults.add((String) msg.obj);
            //updateResult();
            //mAddPlayer.start();
         //   Log.d("Result", "Results " + mResults.get(0));
         }
         break;
      }
      super.handleMessage(msg);
   }
};

private final Thread mReadThread = new Thread() {
   @Override
   public void run() {
      if (mSerialport != null && mSerialport.getFd() > 0) {
         for (int i = 0; i < 10; i ++) {
            mSerialport.read();
            try {
               Thread.sleep(20);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }
      while (mIsRunning) {
         if (mSerialport != null && mSerialport.getFd() > 0) {
            byte[] read = mSerialport.read();
            if (read != null && read.length > 0) {
               mReadBuffer.add(read);
               if (mTask != null) {
                  mTask.cancel();
               }
               if (mTimer != null) {
                  mTimer.purge();
                  mTimer.cancel();
               }
               mTimer = new Timer();
               mTask = new TimerTask() {
                  @Override
                  public void run() {
                     String result = new String();
                     for (int i = 0; i < mReadBuffer.size(); i ++) {
                        result += new String(mReadBuffer.get(i));
                     }
                     Log.d("result", "info Read " + result.toString());
                     myba.raiseEventFromDifferentThread(myba.context, null, 0, eventname + "_datascanned", false, null);
                     Message message = new Message();
                     message.what = MSG_UPDATE;
                     message.obj = result;
                     //mHandler.sendMessage(message);
                     mReadBuffer.clear();
                  }
               };
               mTimer.schedule(mTask, 20);
            }
         }
      }
   }
};


public void scan(BA ba, Boolean Enable){
   mEnable.setTxState(Enable);
}
}

I'm not an expert in Java as you guys can tell, but i'm trying to port this library to make them work with two tablets.

Thanks in advanced for all your help
 
Top