/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000 Tom Cuthill *
* Copyright (C) 2003 Dave Slaughter <dslaughter@safeway.co.uk> *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine is distributed in the hope that it will *
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.io.device.scanner;
import totalcross.sys.*;
import totalcross.ui.*;
import totalcross.ui.dialog.*;
/**
* Scanner accesses some popular barcode scanners.
* <p>
* Scanner access is only available when running on a native TotalCross VM; it
* is not supported when running on Java. It is, though, emulated on Java:
* a popup dialog will ask you for a barcode symbol which will be returned every time
* the <code>getData</code> method is called.
* <p>
* Since there is only one scanner per device, the scanner class is static.
* Activating the scanner causes the physical scanner to be powered, and
* enables the trigger. Deactivating the scanner removes the power from the
* scanner and prevents scans from taking place. The scanner should always
* be deactivated at the end of processing to prevent excessive battery drain.
* <p>
* When the scanner is activated, scan events will appear in the MainWindow's
* onEvent method. The scan events will contain a string describing either
* the item scanned or a battery error. Deactivating the scanner prevents
* scan events from being delivered.
* <p>
* Since barcodes can have many formats, this class includes a method to
* register the barcode types with the scanner. These types must each be
* individually set as parameters to the scanner. After all the parameter
* types have been set, the commitBarcodeParams method must be called to
* register the parameters with the scanner. Once this is done the scanner
* is able to decode the specified barcode types.
* <p>
* A typical processing sequence is given below:
* <pre>
* if (!Scanner.activate() ||
* !Scanner.setBarcodeParam(Intermec.AZTEC, true) ||
* !Scanner.commitBarcodeParams())
* return;
* ...
* if (!Scanner.deactivate())
* return;
* </pre>
*/
public class Scanner
{
public static boolean isActive; // guich@200b4: avoid activate the scanner again
private static String barcode;
private static int tries;
private static boolean driverLoaded;
/** The scanner version. */
public static String scanManagerVersion = Settings.onJavaSE ? "Scanner emulation" : "1.0";
/** Set this listener to send all Scanner events to its onEvent method. */
public static Control listener; // maybe theres another better way to do this...
static
{
if (Settings.isWindowsDevice())
{
driverLoaded = Vm.attachNativeLibrary("Motorola") ||
Vm.attachNativeLibrary("Dolphin") ||
Vm.attachNativeLibrary("Intermec") ||
Vm.attachNativeLibrary("Pidion");
if (!driverLoaded && tries++ == 0)
throw new RuntimeException("Cannot find the native implementation for the scanner library.");
}
}
/**
* Activate the scanner. Return true if the scanner could be activated,
* false otherwise. (A false condition may arise if batteries have run
* too low, or if the unit does not have the scan library installed.
*
* <p><b>Note</b>: On Android Intermec, you can't activate the scanner if it is off in the settings. Moreover, you should not set the scanner and
* virtual wedge settings off and then try to use the scanner. Even though your app won't crash or hang, the device might not behave properly.
* There is no way to check if the device settings are off in the settings or in the app.
*/
public static boolean activate()
{
isActive = scannerActivate();
scanManagerVersion = getScanManagerVersion();
return isActive;
}
static boolean scannerActivate()
{
InputBox id = new InputBox("Barcode emulation","Please enter the barcode:","");
id.popup();
barcode = id.getValue();
_onEvent(ScanEvent.SCANNED);
return true;
}
native static boolean scannerActivate4D();
/**
* Set a scanner parameter defining whether a barcode format will be used
* in scanning. Choose from one of the barcode types given above.
* @param barcodeType the type of barcode under consideration
* @param enable a flag to enable or disable decoding barcodes of this type.
*
* <p><b>Note</b>: On Android Intermec, you CAN'T set enable a barcode type the scanner is not activate. In this case, this method will return false.
*/
public static boolean setBarcodeParam(int barcodeType, boolean enable)
{
return true;
}
native public static boolean setBarcodeParam4D(int barcodeType, boolean enable);
/**
* Set a parameter for the barcode. You can use the xxx_PARAM constants to
* know which parameter to set, and also the values below for their values.
* Be careful because some functions may require also the barcode type.
* <p>
* With Datalogic scanners, the SECOND parameter is not used (always pass 0 to it);
* and don't forget to call the commitBarcodeParams method.
* <p> Values valid for SYMBOL scanners:
* <pre>
* // triggering modes
* #define LEVEL 0x00
* #define PULSE 0x02
* #define HOST 0x08
*
* // Linear code type security
* #define SECURITY_LEVEL0 0x00
* #define SECURITY_LEVEL1 0x01
* #define SECURITY_LEVEL2 0x02
* #define SECURITY_LEVEL3 0x03
* #define SECURITY_LEVEL4 0x04
*
* // UPC/EAN Supplementals
* #define IGNORE_SUPPLEMENTALS 0x00
* #define DECODE_SUPPLEMENTALS 0x01
* #define AUTODISCRIMINATE_SUPPLEMENTALS 0x02
*
* // Transmit Check Digit options
* #define DO_NOT_TRANSMIT_CHECK_DIGIT 0x00
* #define TRANSMIT_CHECK_DIGIT 0x01
*
* // Preamble options
* #define NO_PREAMBLE 0x00
* #define SYSTEM_CHARACTER 0x01
* #define SYSTEM_CHARACTER_COUNTRY_CODE 0x02
*
* // CheckDigit verification options
* #define DISABLE_CHECK_DIGIT 0x00
* #define USS_CHECK_DIGIT 0x01
* #define OPCC_CHECK_DIGIT 0x02
*
* // MSI Plessey checkdigit options
* #define ONE_CHECK_DIGIT 0x00
* #define TWO_CHECK_DIGITS 0x01
*
* // MSI Plessey check digit algorithms
* #define MOD10_MOD11 0x00
* #define MOD10_MOD10 0x01
*
* // Transmit Code ID Character options
* #define AIM_CODE_ID_CHARACTER 0x01
* #define SYMBOL_CODE_ID_CHARACTER 0x02
*
* // Scan data transmission formats
* #define DATA_AS_IS 0x00
* #define DATA_SUFFIX1 0x01
* #define DATA_SUFFIX2 0x02
* #define DATA_SUFFIX1_SUFFIX2 0x03
* #define PREFIX_DATA 0x04
* #define PREFIX_DATA_SUFFIX1 0x05
* #define PREFIX_DATA_SUFFIX2 0x06
* #define PREFIX_DATA_SUFFIX1_SUFFIX2 0x07
*
* // Scan angle options
* #define SCAN_ANGLE_WIDE 0xB6
* #define SCAN_ANGLE_NARROW 0xB5
* </pre>
* <p> This method is ignored for Intermec scanners.
*/
public static boolean setParam(int type, int barcodeType, int value) // guich@330_43
{
return true;
}
native public static boolean setParam4D(int type, int barcodeType, int value);
/**
* Commit the barcode parameters to the scanner. Returns true if the
* operation is successful and false, otherwise.
* <p> Not used on the Windows CE and Android platforms.
*
*/
public static boolean commitBarcodeParams()
{
return true;
}
native public static boolean commitBarcodeParams4D();
/**
* Set the length of a barcode.
*
* <p> This method is ignored for Intermec scanners.
*
* The lengthType must be one of the following values:
* @param barcodeType One of the BARxxxx constants
* @param lengthType 0 (variables length, min, and max are ignored), 1 (length = min), 2 (length = min || length = max), 3 (min <= length <= max). Careful: in Motorola Scanners, min and max must be used in inverted order due to a bug in the MOTOROLA API.
* @param min The minimum value
* @param max The maximum value
*/
public static boolean setBarcodeLength(int barcodeType, int lengthType, int min, int max) // guich@330_43
{
return true;
}
native public static boolean setBarcodeLength4D(int barcodeType, int lengthType, int min, int max);
/**
* Get the decoded string of what has been scanned. If an error occurs a
* null String will be returned.
*
* <p><b>Note</b>: On Android Intermec, you should first set some parameters before fetching data or else it might crash after 10 or 15 reads.
*/
public static String getData()
{
return barcode;
}
native public static String getData4D();
/**
* Get the scan manager version as an hexadecimal String. If an error occurs or if this method
* is called before the Scanner is initialized, a null String will be returned.
*/
public static String getScanManagerVersion()
{
return "Scanner emulation";
}
native public static String getScanManagerVersion4D(); //return !isActive?null:scannerGetScanManagerVersion();
/**
* Get the Scanner Port Driver version as an hexadecimal string. If an error occurs or if this method
* is called before the Scanner is initialized, a null string will be returned.
*/
public static String getScanPortDriverVersion()
{
return null;
}
native public static String getScanPortDriverVersion4D(); // !isActive?null:scannerGetScanPortDriverVersion();
/**
* Deactivate the scanner. Returns true if the operation is successful
* and false, otherwise.
*/
public static boolean deactivate()
{
isActive = false;
return true;
}
native public static boolean deactivate4D(); //if (isActive) isActive = !scannerDeactivate(); return !isActive;
private static ScanEvent se = new ScanEvent();
/** Dispatch the event to the current listener (associated through the
* <code>listener</code> public member. Called from the native library.
* If there are no assigned listeners, the event is sent to the top most window,
* and the window is validated.
*/
protected static void _onEvent(int type)
{
Control dest = listener;
if (dest == null)
dest = Window.getTopMost();
// convert from the type to the internal event id
int id = type == 2 ? ScanEvent.BATTERY_ERROR :
type == 1 ? ScanEvent.SCANNED
/* 0 */ : ScanEvent.TRIGGERED;
// dispatch to the listener
se.update(id);
dest.postEvent(se);
}
/** Reads a barcode using ZXing for Android.
*
* The mode can be one of:
* <ul>
* <li> 1D - for one dimension barcodes
* <li> 2D - for QR codes
* <li> empty string - for both
* </ul>
*
* If an error happens, it is returned prefixed with ***.
*
* See the TotalCross API / Scanner Camera sample.
*/
public static String readBarcode(String mode)
{
return null;
}
native public static String readBarcode4D(String mode);
}