Print barcode using thermal printer Android - android

I was able to print text but when it comes to barcode it not showing or just showing irregular text.
Here is my source code
//barcode 128
byte[] formats = {(byte) 0x1d, (byte) 0x6b, (byte) 0x73,(byte) 0x0d};
byte[] contents = content.getBytes();
byte[] bytes = new byte[formats.length + contents.length];
System.arraycopy(formats, 0, bytes, 0, formats.length );
System.arraycopy(contents, 0, bytes, formats.length, contents.length);
usbCtrl.sendByte(bytes, dev);
usbCtrl.sendByte(LineFeed(), dev);
but the result barcode is not showing, am i missing something
Please help me
EDIT
I found the ESC/POS code :
GS k m d1...dk NUL or GS k m n d1...d k
But when I try this, still got same result

The GS k POS code has two versions (as you already discovered):
GS k - print one dimensional barcode
m - barcode mode selector
[d]k - data bytes
NUL - terminator
This version works only for pure ASCII data since it uses a 0x00 (NUL) as terminator.
GS k - print one dimensional barcode
m - barcode mode selector
n - content length in bytes
[d]k - data bytes
This version uses an additional length byte n to indicate the data part (it's also only suitable for certain codings including CODE128).
Your code has a stray 0x0d in the command bytes and may also be using the wrong format.
If you plan to print pure ASCII data format the command like this:
byte[] formats = {(byte) 0x1d, (byte) 0x6b, (byte) 0x49};
byte[] contents = content.getBytes();
byte[] bytes = new byte[formats.length + contents.length + 1];
System.arraycopy(formats, 0, bytes, 0, formats.length );
System.arraycopy(contents, 0, bytes, formats.length, contents.length);
// add a terminating NULL
bytes[formats.length + contents.length] = (byte) 0x00;
Or the more secure version since it also has the expected data length:
byte[] contents = content.getBytes();
// include the content length after the mode selector (0x49)
byte[] formats = {(byte) 0x1d, (byte) 0x6b, (byte) 0x49, (byte)content.length};
byte[] bytes = new byte[formats.length + contents.length];
System.arraycopy(formats, 0, bytes, 0, formats.length );
System.arraycopy(contents, 0, bytes, formats.length, contents.length);
If neither of the two work then your printer may simply not support CODE128.
The 5890 is a common enough specification and there are lots of cheap "drop-in" replacements on the market which leave out the more complex barcode implementations and only include simple codings like EAN8, EAN13 etc.

Related

ESC/POS Long String Barcode Not Scanable

I'm working on Chinese Bluetooth thermal printer Model:SCAN-X, Problem is barcodes for long strings are not scannable:
0123456789 -- printed & scannable
abcdefghijklmno -- printed & not scannable
INV-1-48 -- printed & scannable
INW-0001-0000000047 --- printed & not scannable
INW-001-0123456789 --- printed & scannable
INW-0001-123456789 --- printed & not scannable
Here is specified guide in ESC/POS doc of printer
I am bit confused is there something wrong with my code?
private void printBarcodeTest() {
OutputStream out = null;
try {
if ((socket == null) || (!socket.isConnected())) {
socket = BluetoothUtil.getSocket(mBluetoothPrinterDevice);
}
out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
// String barcodeContent1 = "INW-1-47"; // this is printing fine
String barcodeContent1 = "INW-0001-0000000047"; // this is printing, but not readable by barcode scanner
byte[] format = new byte[]{
0x1D, // GS
0x6B, // k
(byte) 73, // m (2) this is CODE_128
(byte) barcodeContent1.length() // n (number of barcode data bytes)
};
byte[] data = ESCUtil.byteMerger(new byte[][]{
format,
barcodeContent1.getBytes(StandardCharsets.UTF_8) //d1...dn
});
if (out != null) {
// init printer
// ESC , #
writeOutStream(out, new byte[]{0x1B, 0x40});
// // left margin
// // GS , L , nL , nH
// writeOutStream(out,new byte[]{ 0x1D , 0x4C ,(byte) (0 % 256),(byte) (0 / 256)});
// set alignment to center
// ESC ,a , n
writeOutStream(out, new byte[]{0x1B, 0x61, (byte) 1});
// set HRI position
// GS , ! , n
writeOutStream(out, new byte[]{0x1D, 0x48, (byte) 2});
// set height
// GS , h , n
writeOutStream(out, new byte[]{0x1D, 0x68, (byte) 2});
// set width
// GS , w , n
writeOutStream(out, new byte[]{0x1D, 0x77, (byte) 16);
// set data to print
writeOutStream(out, data);
// set next line feed
// LF
writeOutStream(out, new byte[]{0x0A});
// print n dots in feed
// ESC , J , n
writeOutStream(out, new byte[]{0x1B, 0x4A, (byte) 160});
}
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Output:
Can anyone please take a look and guide me?
Okay, it isn't the quiet zones or bounding box or the software. The problem is with the print head. There is too much bleed between the bars. If you printed out 100 of the '...0047' codes, maybe a fraction of them would scan.
Your print head (thermal, I think?) isn't cooling down enough between the bars to leave white spaces. This may be because the paper is too sensitive to heat, it may be because the print head is not designed for such tight spacing, or it may be a bad print head.
Here are some things you might want to try:
Another printer, if one is available, this might help you isolate a bad printer.
Scaling up the barcode width about 50%, increasing the space between bars. Try "writeOutStream(out, new byte[]{0x1D, 0x77, (byte) 24);"
Use Code 128C for the large numeric portion on the right. I'm not sure how to switch to Code 128C from Code 128B using that setup, but it could shorten the entire barcode symbol by 4 characters.

APDU Case 2 Response too short

I'm using a ACR39T-A3 Smart Card Reader connected over USB to an Android device.
First I'm sending a APDU Case 2 command like this.
int offset = 0;
List<byte[]> dataList = new ArrayList<>(8);
while (true) {
if (!responseString.contains("90 00")) {
break;
}
dataList.add(progress[0].response);
int offsetStartInt = 0x7F & (offset >> 8);
int offsetEndInt = offset & 0xFF ;
//SmartcardOS
//T1
byte[] apdu = new byte[]{
(byte) 0x00, //CLA
(byte) 0xB0, //INS
(byte) offsetStartInt, //P1
(byte) offsetEndInt, //P2
(byte) 0xff, //LE
};
transmitApdu(apdu);
offset += 256;
}
Im trying to get a certificate from the Smartcard.
The certificate can be bigger than 256 so i need send multiple.
But as Response i just get 90 00 instead of the certificate in mulitple.
Can anybody help me? I donĀ“t understand how does it work with the offset.
While I don't recognize your API (and responseString is somewhat too magically filled in my opinion), in principle it should work that way.
Since you specify LE as 0xFF, I recommend either
to set LE to zero instead or
to increment offset only by 255.
If your EF was not yet written to at all, some cards may return nothing but 90 00.

NFC-V "Tag Lost" exception with Xamarin and ST M24LR tag

I am new to Xamarin as well as Android development. I have an NFC tag, specifically a ST M24LR64E, with data on it. I can see the blocks of data using the ST app on Google Play. In my Xamarin app, I cannot send a message to the tag without getting a TagLostException. I can query the tag ID with no issue, but trying to read a single block of data, I get the exception. Any direction would be grateful.
byte[] response = new byte[] { 0x0A };
byte[] cmd = new byte[]
{
(byte) 0x26,
(byte) 0x01,
0x00
};
response = nfcv.Transceive(cmd);
byte[] single = new byte[]
{
(byte) 0x40, // FLAGS
(byte) 0x20, // READ_SINGLE_BLOCK
0, 0, 0, 0, 0, 0, 0, 0,
(byte) (0 & 0x0ff)
};
Array.Copy(id, 0, single, 2, 8);
response = nfcv.Transceive(single);
The first Transceive() is ok and I see 10 bytes coming back. As soon as I try to read a block of data, I get the TagLostException.
With the NfcV tag technology, a TagLostException may indicate that the reader can no longer communicate with the tag or that the command resulted in an error.
According to its manual, the M24LR64E only supports the extended version (Protocol Extension flag set) of the READ_SINGLE_BLOCK command:
The Protocol_extension_flag should be set to 1 for the M24LR64E-R to operate correctly. If the Protocol_extension_flag is at 0, the M24LR64E-R answers with an error code.
Consequently, your version of the READ_SINGLE_BLOCK command is not compatible with the tag. You need to set the Protocol Extension flag and provide a 16 bit block number. A version that should work is:
int blockNumber = 0;
byte[] readSingleBlock = new byte[] {
(byte) 0x28, // Flags: Addressed (bit 5), Protocol Extension (bit 3)
(byte) 0x20, // Command: READ_SINGLE_BLOCK
0, 0, 0, 0, 0, 0, 0, 0, // placeholder for UID
(byte) (blockNumber & 0x0ff),
(byte) ((blockNumber >> 8) & 0x0ff)
};
byte[] id = nfcv.GetTag().GetId();
Array.Copy(id, 0, readSingleBlock, 2, 8);
response = nfcv.Transceive(readSingleBlock);
Since you used the high data rate (Data_rate flag set) with the INVENTORY command, you might also want to use the high data rate with the READ_SINGLE_BLOCK command. You would use the flags value 0x2A (instead of 0x28) in that case.
Finally, you should avoid sending anti-collision/enumeration commands such as the INVENTORY command over any NfcX tag technology object. While this may work, you might confuse the internal state-keeping of the ANdroid NFC stack since it already performs these commands for you and keeps track of the enumerated tag(s). You can get all the information that you would obtain through the INVENTORY request from the Tag object and the NfcV object:
tag.GetId() gives you the UID of the tag.
nfcv.GetDsfId() gives you the DSFID of the tag.
nfcv.GetResponseFlags() gives you the flags byte of the INVENTORY response.

Android NFC read from tag type: IsoDep and NfcB

I am very new to Android development and NFC in general.
I am trying to build an application to read the content of an NFC card where I don't know anything about this card (bus card), I want to see for example how many tickets I have left.
I have scanned the card with variety of NFC applications and know that this card is of type: IsoDep AND NfcB.
Right now I am trying to read its content using IsoDep with no success (errors 6A82, 91AE, 6E00 and so on).
I have an app that waiting for new intent of type ACTION_NDEF_DISCOVERED || ACTION_TECH_DISCOVERED || ACTION_TAG_DISCOVERED opens a new thread (since it is not possible to read and connect on UI's thread) and I am trying to read the content of the card.
I guess my problem is with the bytes I am passing to isoDep.transceive(NATIVE_SELECT_APP_COMMAND).
Should I keep trying on the IsoDep or should I move to try on the NfcB?
Do you guys have any tips?
here is my code sample:
final byte[] SELECT = {
(byte) 0x00, // CLA Class
(byte) 0xA4, // INS Instruction
(byte) 0x04, // P1 Parameter 1
(byte) 0x00, // P2 Parameter 2
(byte) 0x08, // Length
(byte) 0x31, (byte)0x54, (byte)0x49, (byte)0x43, (byte)0x2e,
(byte) 0x49, (byte)0x43, (byte)0x41, // AID 315449432e494341
};
Tag tagFromIntent = m_intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep isoDep = IsoDep.get(tagFromIntent);
try {
isoDep.connect();
byte[] result = isoDep.transceive(SELECT);
String str = bytesToHex(result);
Log.i("test", "SELECT: " + str);
isoDep.close();
} catch (Exception e) {
String error = e.getMessage();
}
my bytes to hex function:
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
=============================================================
Edit:
I have just learned that this card is using Calypso authentication scheme.
In this question's answer helped me a little: Read data from NFC tag (IsoDep)
I found a good SELECT function, i have edited my question to hold the new "SELECT" command which is working- In return i get this string: "6F228408315449432E494341A516BF0C13C70800000000029780A55307060A07062004019000" which i have no idea what it means.
Then I use this command to try and read a string:
byte[] GET_STRING = {
(byte) 0x80, // CLA Class
0x04, // INS Instruction
0x00, // P1 Parameter 1
0x00, // P2 Parameter 2
0x10 // LE maximal number of bytes expected in result
};
But i get error: 6E00, any ideas on how to proceed?
You could communicate with card with IsoDep.
You want to access data on card without specifications of this card, so there's 2 ways:
Get specification of card (how to communicate with it)
Do reverse engineering, it will take lot of time and not sure about the result, and you could "lock" access to the card
UPDATE 1
To read Rav Kav card, threre's an open-source project : http://pannetrat.com/Cardpeek/ code for Rav Kav is here https://code.google.com/p/cardpeek/source/browse/trunk/dot_cardpeek_dir/scripts/calypso/c376n3.lua
You are sending the wrong command to read the application's records. 6E00 means incorrect INS byte.
You can have a look at this github which reads some counters out of a MOBIB card, which is based on the Calypso spec.
https://github.com/flamingokweker/Android-NFC-Mobib-Reader

Read data from NFC tag (IsoDep)

I am newbie in Android NFC API.
Currently, I have a NFC tag, I am making an Android app to read data from it. My simple App is launched when my phone get closer enough to the NFC Tag. But I have no idea how to read the data inside the NFC Tag. The tag uses IsoDep technology.
My current code:
#Override
protected void onResume (){
super.onResume();
Intent intent = getIntent();
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep isoDep = IsoDep.get(tag);
// How to read data from IsoDep instance?
I googled on internet, I notice people are sending commands to IsoDep to get response from NFC Tag, I suppose from the response, we can parse the data in the tag, I saw people doing this:
//What is the 'command' ? How to define the command?
//e.g.:
byte command = (byte) 0x6A
isoDep.transceive(command)
But, the command is just a byte, as a newbie, it is too difficult to understand what is happening. I have no idea how to define the command to read data? Anyone can explain to me? or is there a document I can learn about the command?
Generally, I need some guidance on how to define commands & how to parse data from response, I would like to read the data stored in the Tag & show the data in String format in UI element (e.g. TextView).
*AND***
I have no problem with those configurations(e.g. AnroidManifest.xml), please don't guide me on how to configure :)
IsoDep allows you to communicate over a ISO-14443-4 connection with the transceive operation. Over this protocol application data units (APDUs) are exchanged. The format is specified, you find a description on Wikipedia.
For exaple, to select an application on a smart card with a particular application identifier (AID) you would execute the following APDU command. The result simply indicates ok (9000) or an error.
byte[] SELECT = {
(byte) 0x00, // CLA Class
(byte) 0xA4, // INS Instruction
(byte) 0x04, // P1 Parameter 1
(byte) 0x00, // P2 Parameter 2
(byte) 0x0A, // Length
0x63,0x64,0x63,0x00,0x00,0x00,0x00,0x32,0x32,0x31 // AID
};
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep tag = IsoDep.get(tagFromIntent);
tag.connect();
byte[] result = tag.transceive(SELECT);
if (!(result[0] == (byte) 0x90 && result[1] == (byte) 0x00))
throw new IOException("could not select applet");
After the application has been selected, you can execute application specific commands. The programs are typically written in JavaCard which follows the GlobalPlatorm spec. The following example executes on the above selected application the method 4 (0x04) which returns a byte array of at most 11 bytes. This result is then converted to a string.
byte[] GET_STRING = {
(byte) 0x80, // CLA Class
0x04, // INS Instruction
0x00, // P1 Parameter 1
0x00, // P2 Parameter 2
0x10 // LE maximal number of bytes expected in result
};
result = tag.transceive(GET_STRING);
int len = result.length;
if (!(result[len-2]==(byte)0x90&&result[len-1]==(byte) 0x00))
throw new RuntimeException("could not retrieve msisdn");
byte[] data = new byte[len-2];
System.arraycopy(result, 0, data, 0, len-2);
String str = new String(data).trim();
tag.close();

Categories

Resources