Android: 生成 EAN13 条形码
快速 EAN13 条形码生成类。
引言
欧洲商品编号,或 EAN,是一种标准的欧洲条形码,旨在对产品及其制造商的标识进行编码,并且是美国标准 UPC 的超集。 EAN13 条形码的格式对一个 12 个字符的字符串进行编码,后跟一个第 13 个字符,该字符充当控制号,并通过一个基于前 12 个字符的公式计算得出。
如今,条形码无处不在。 如果您以程序员为生,那么迟早您会在您的应用程序中需要支持条形码。 例如,这可能是一个超市奖励系统,用户通过手机上的条形码进行识别以获得折扣,或者像星巴克移动支付网络这样的支付系统。 在本文中,我们将看到如何在 Android 屏幕上生成 EAN13 条形码。
本文的俄语版本可以在这里找到: http://blog.plaincodesource.ws/2011/02/android-ean13.html。
EAN13 计算基础
EAN13 条形码使用一个 12 位的产品代码,第十三位数字是控制号,它是在前 12 位的基础上计算出来的。 控制号的计算(数字从右向左编号)如下
- P1 = 偶数位的总和
- P2 = 奇数位的总和
- Z = P1 + 3 * P2
- R = 立即大于 Z 且能被 10 整除的数字
- 控制号 = R - Z
接下来,让我们看看 EAN13 编码系统
- 第一个数字未被编码
- 接下来的 6 位数字根据第一个数字进行编码
- 最后 6 位数字按照严格的规则转换
第一个数字 | 左边 6 位数字 | 右边 6 位数字 |
0 | LLLLLL | RRRRRR |
1 | LLGLGG | RRRRRR |
2 | LLGGLG | RRRRRR |
3 | LLGGGL | RRRRRR |
4 | LGLLGG | RRRRRR |
5 | LGGLLG | RRRRRR |
6 | LGGGLL | RRRRRR |
7 | LGLGLG | RRRRRR |
8 | LGLGGL | RRRRRR |
9 | LGGLGL | RRRRRR |
数字编码
数字 | L - 代码 | G - 代码 | R - 代码 |
0 | 0001101 | 0100111 | 1110010 |
1 | 0011001 | 0110011 | 1100110 |
2 | 0010011 | 0011011 | 1101100 |
3 | 0111101 | 0100001 | 1000010 |
4 | 0100011 | 0011101 | 1011100 |
5 | 0110001 | 0111001 | 1001110 |
6 | 0101111 | 0000101 | 1010000 |
7 | 0111011 | 0010001 | 1000100 |
8 | 0110111 | 0001001 | 1001000 |
9 | 0001011 | 0010111 | 1110100 |
实现
我们有 EAN13CodeBuilder
,它是一个将 12 个数字序列编码成 EAN-13 条形码中的文本字符串的类,然后可以使用一个特殊字体在屏幕上显示该字符串,其中每个字符都被条形码替换。 这种字体包含一些特殊字符,例如 $, +, !,以及上述 L、R 和 G 代码的 10 个数字集。 EAN13 条形码字符串必须以下列方式构建:开始分隔符(取决于第一个数字) - 左边 6 个符号 - 中间分隔符 (-) - 右边 6 个符号 - 结束分隔符 (!)
数字 | L - 代码 | G - 代码 | R - 代码 | 开始分隔符 |
0 | 0 | A | a | #! |
1 | 1 | B | b | $! |
2 | 2 | C | c | %! |
3 | 3 | D | d | &! |
4 | 4 | E | e | '! |
5 | 5 | F | f | (! |
6 | 6 | G | g | )! |
7 | 7 | H | h | *! |
8 | 8 | 我 | i | +! |
9 | 9 | J | j | ,! |
我们只需要从数字生成正确的字符串,然后使用这种特殊字体显示它。
这个类的使用非常简单。 它将原始字符串输入到构造函数中,然后 getcode()
方法将字符串返回到 EAN-13 中。 类的源代码如下所示
/*
* (C) 2011 Slava Archibasov
* http://blog.plaincodesource.ws
*
* This code is licensed under The Code Project Open License (CPOL)
* https://codeproject.org.cn/info/cpol10.aspx
*/
public class EAN13CodeBuilder {
private String codeStringValue;
private String generatedCode;
public EAN13CodeBuilder(String codeString)
{
codeStringValue = codeString;
parse();
}
public String getCode()
{
return generatedCode;
}
////////////////////////////////////////////////////////////////
// this method generates EAN 13 control number ans returns full
// string to encode
private String getFullCode()
{
int chetVal = 0, nechetVal = 0;
String codeToParse = codeStringValue;
for( int index = 0;index<6;index++ )
{
chetVal += Integer.valueOf(codeToParse.substring(
index*2+1,index*2+2)).intValue();
nechetVal += Integer.valueOf(codeToParse.substring(
index*2,index*2+1)).intValue();
}
chetVal *= 3;
int controlNumber = 10 - (chetVal+nechetVal)%10;
if( controlNumber == 10 ) controlNumber = 0;
codeToParse += String.valueOf(controlNumber);
return codeToParse;
}
private String DigitToUpperCase( String digit)
{
String letters = "ABCDEFGHIJ";
int position = Integer.valueOf(digit).intValue();
String retVal = letters.substring(position,position+1);
return retVal;
}
private String DigitToLowerCase( String digit)
{
String letters = "abcdefghij";
int position = Integer.valueOf(digit).intValue();
String retVal = letters.substring(position,position+1);
return retVal;
}
//////////////////////////////////////////////
// this method generates EAN 13 encoded string
// algorithm can be found at http://en.wikipedia.org/wiki/EAN-13
private String createEAN13Code(String rawCode)
{
int firstFlag = Integer.valueOf(
rawCode.substring(0,1)
).intValue();
String leftString = rawCode.substring(1,7);
String rightString = rawCode.substring(7);
String rightCode = "";
String leftCode = "";
for( int i=0;i<6;i++)
{
rightCode += DigitToLowerCase( rightString.substring(i,i+1) );
}
if( firstFlag == 0 )
{
leftCode = "#!"+leftString.substring(0,1)
+leftString.substring(1,2)
+leftString.substring(2,3)
+leftString.substring(3,4)
+leftString.substring(4,5)
+leftString.substring(5);
}
if( firstFlag == 1 )
{
leftCode = "$!"+leftString.substring(0,1)
+leftString.substring(1,2)
+DigitToUpperCase(leftString.substring(2,3))
+leftString.substring(3,4)
+DigitToUpperCase(leftString.substring(4,5))
+DigitToUpperCase(leftString.substring(5));
}
if( firstFlag == 2 )
{
leftCode = "%!"+leftString.substring(0,1)
+leftString.substring(1,2)
+DigitToUpperCase(leftString.substring(2,3))
+DigitToUpperCase(leftString.substring(3,4))
+leftString.substring(4,5)
+DigitToUpperCase(leftString.substring(5));
}
if( firstFlag == 3 )
{
leftCode = "&!"+leftString.substring(0,1)
+leftString.substring(1,2)
+DigitToUpperCase(leftString.substring(2,3))
+DigitToUpperCase(leftString.substring(3,4))
+DigitToUpperCase(leftString.substring(4,5))
+leftString.substring(5);
}
if( firstFlag == 4 )
{
leftCode = "'!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+leftString.substring(2,3)
+leftString.substring(3,4)
+DigitToUpperCase(leftString.substring(4,5))
+DigitToUpperCase(leftString.substring(5));
}
if( firstFlag == 5 )
{
leftCode = "(!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+DigitToUpperCase(leftString.substring(2,3))
+leftString.substring(3,4)
+leftString.substring(4,5)
+DigitToUpperCase(leftString.substring(5));
}
if( firstFlag == 6 )
{
leftCode = ")!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+DigitToUpperCase(leftString.substring(2,3))
+DigitToUpperCase(leftString.substring(3,4))
+leftString.substring(4,5)
+leftString.substring(5);
}
if( firstFlag == 7 )
{
leftCode = "*!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+leftString.substring(2,3)
+DigitToUpperCase(leftString.substring(3,4))
+leftString.substring(4,5)
+DigitToUpperCase(leftString.substring(5));
}
if( firstFlag == 8 )
{
leftCode = "+!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+leftString.substring(2,3)
+DigitToUpperCase(leftString.substring(3,4))
+DigitToUpperCase(leftString.substring(4,5))
+leftString.substring(5);
}
if( firstFlag == 9 )
{
leftCode = ",!"+leftString.substring(0,1)
+DigitToUpperCase(leftString.substring(1,2))
+DigitToUpperCase(leftString.substring(2,3))
+leftString.substring(3,4)
+DigitToUpperCase(leftString.substring(4,5))
+leftString.substring(5);
}
String retVal = leftCode + "-" + rightCode + "!";
return retVal;
}
private void parse()
{
String fullString = getFullCode();
System.out.println( "Full code: " + fullString );
generatedCode = createEAN13Code(fullString);
System.out.println( "Generated code: " + generatedCode );
}
}
使用代码
要生成条形码行并将其带到 Android 屏幕上,您应该生成条形码字符串本身,并使用其中一种条形码字体在屏幕上显示它。 要在 Android 中的 TextView
控件中设置字体,请将 TTF 文件放在 /assets 项目文件夹中,加载 Typeface
,并将此 Typeface
设置为 TextView
。
例如,您可以使用以下代码
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.graphics.Typeface;
public class AndroidEAN13Activity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// ToDo add your GUI initialization code here
this.setContentView(R.layout.main);
TextView t = (TextView)findViewById(R.id.barcode);
// set barcode font for TextView.
// ttf file must be placed is assets/fonts
Typeface font = Typeface.createFromAsset(this.getAssets(),
"fonts/EanP72Tt Normal.Ttf");
t.setTypeface(font);
// generate barcode string
EAN13CodeBuilder bb = new EAN13CodeBuilder("124958761310");
t.setText(bb.getCode());
}
}