Android でバーコードというと QR コードの話が中心になりがちですが、実務では 1 次元バーコード(CODE_128 や NW-7 など)を扱う場面も少なくありません。会員証やクーポン、在庫管理のコードなど、意外と身近なところで登場します。
そして 1 次元バーコードでよくつまずくのが、「CODE_128 と NW-7(Codabar)のどちらを使うのか」という判断と、start / stop 文字の扱いです。この違いを知らずに実装すると、「生成はできたのにリーダーで読めない」といった地味なトラブルにハマります。この記事では、ZXing を使った生成・読み取りの基本と、この2つのフォーマットの違いを整理していきます。
まず ZXing 系ライブラリの構成を押さえる
Android で ZXing を使うときは、役割の違う2つのライブラリを意識すると分かりやすいです。
com.google.zxing:core― バーコードの生成・デコードを担う純 Java ライブラリ。画像(Bitmap)を作るのはこちら。com.journeyapps:zxing-android-embedded― カメラでスキャンするための Android 向けラッパー。読み取り UI を提供する。
依存関係はこう書きます(バージョンは最新の安定版に置き換えてください)。スキャンも生成も両方使う場合、embedded 側が core を内包しているので、これだけで足ります。
dependencies {
// スキャン用(core を内包)
implementation("com.journeyapps:zxing-android-embedded:X.Y.Z")
// 生成だけなら core 単体でも可
// implementation("com.google.zxing:core:X.Y.Z")
}
バーコードを生成する
生成は MultiFormatWriter で BitMatrix を作り、BarcodeEncoder で Bitmap に変換して ImageView に表示する、という流れです。まずは CODE_128 の例から。
private fun generateCode128(content: String): Bitmap? {
return try {
val writer = MultiFormatWriter()
// 幅600 × 高さ200 で CODE_128 を生成
val bitMatrix = writer.encode(
content, BarcodeFormat.CODE_128, 600, 200
)
BarcodeEncoder().createBitmap(bitMatrix)
} catch (e: WriterException) {
// 不正なコンテンツなどでエンコードに失敗
null
}
}
生成した Bitmap は、そのまま ImageView にセットするだけです。
val bitmap = generateCode128("SAMPLE12345")
if (bitmap != null) {
binding.barcodeImage.setImageBitmap(bitmap)
}
CODE_128 と NW-7(Codabar)の違い
ここが本題です。まず前提として、NW-7 と Codabar は同じものを指します(日本では NW-7、海外では Codabar と呼ばれることが多い)。ZXing 上のフォーマット名は BarcodeFormat.CODABAR です。
2つの主な違いを整理すると、次のようになります。
- 扱える文字:CODE_128 は数字・英大小文字・記号など ASCII 全般を扱える。NW-7 は数字と一部の記号(
- $ : / . +)に限られる。 - 密度:CODE_128 は高密度で、同じ桁数でも幅を抑えやすい。NW-7 は比較的低密度。
- start / stop 文字:ここが最大の違い。NW-7 は start / stop 文字(A〜D)が仕様の一部で、コードの先頭と末尾に付く。CODE_128 は start / stop を内部的に持つため、コンテンツ側で意識する必要がない。
- チェックデジット:CODE_128 は仕様上チェックサムを内蔵する。NW-7 は必須ではなく、運用側でルールを決めることが多い。
- 用途:CODE_128 は物流・出荷ラベルなど汎用的に。NW-7 は図書館・血液バッグ・一部の会員証など、歴史的に使われてきた分野で今も現役。
実装で効いてくるのは start / stop
実装時にいちばん事故りやすいのが、この start / stop 文字です。NW-7 を生成するときは、コンテンツの先頭と末尾に start / stop 文字(A〜D)を含める前提で考えるのが安全です。
private fun generateCodabar(rawNumber: String): Bitmap? {
// 例: start/stop に A を付ける(A + 本体 + A)
val content = "A" + rawNumber + "A"
return try {
val bitMatrix = MultiFormatWriter().encode(
content, BarcodeFormat.CODABAR, 600, 200
)
BarcodeEncoder().createBitmap(bitMatrix)
} catch (e: WriterException) {
null
}
}
ZXing のエンコーダは start / stop が無いときにデフォルトを補うこともありますが、読み取り側(リーダーや連携先システム)が特定の start / stop(たとえば A…A や A…B)を期待するケースがあります。連携仕様がある場合は、その指定に合わせて明示的に付けるのが確実です。「生成はできるのに連携先で弾かれる」ときは、まずこの start / stop を疑うとよいでしょう。
バーコードを読み取る(スキャン)
スキャンは ScanContract と registerForActivityResult を組み合わせるのが今の推奨です(従来の startActivityForResult や IntentIntegrator は非推奨)。
// ランチャーは初期化時に登録する
private val barcodeLauncher = registerForActivityResult(ScanContract()) { result ->
if (result.contents == null) {
// キャンセルされた
} else {
// 読み取った文字列
onBarcodeScanned(result.contents)
}
}
private fun startScan() {
val options = ScanOptions().apply {
// 読み取り対象のフォーマットを絞る
setDesiredBarcodeFormats(
ScanOptions.CODE_128,
ScanOptions.CODABAR
)
setPrompt("バーコードを枠内に合わせてください")
setBeepEnabled(true)
setOrientationLocked(false)
}
barcodeLauncher.launch(options)
}
読み取り対象のフォーマットを setDesiredBarcodeFormats で絞っておくのがポイントです。指定しないと全フォーマットを対象にするため、似た形状のコードを誤読しやすくなります。扱うコードが決まっているなら、必ず絞り込んでおくと精度が安定します。
カメラを使うので、AndroidManifest.xml にカメラのパーミッションを宣言しておきます。実行時の権限リクエストはスキャン用の Activity 側で処理されます。
<uses-permission android:name="android.permission.CAMERA" />
ハマりやすいポイント
- NW-7 の start / stop 忘れ ― 連携先が期待する start / stop を含めていないと、読めても検証で弾かれる。
- フォーマットを絞っていない ― 全対象のままだと誤読しやすい。扱うコードだけを指定する。
- NW-7 に非対応文字を入れる ― 英字や多くの記号は使えない。数字前提で設計する。
- 非推奨 API の利用 ―
startActivityForResult/IntentIntegratorではなくScanContractを使う。
まとめ
- 生成は
MultiFormatWriter+BarcodeEncoder、スキャンはScanContract+registerForActivityResult。 - CODE_128 は高密度で ASCII 全般対応、start / stop は内部処理。汎用ならこちら。
- NW-7(Codabar)は数字中心で、start / stop 文字(A〜D)を明示するのが実装の勘所。
- スキャン時は対象フォーマットを絞って誤読を防ぐ。
1 次元バーコードは「動いた/動かない」が start / stop やフォーマット指定といった細かい仕様で決まりがちで、そこを押さえておくと調査もぐっと楽になります。連携仕様書がある場合は、フォーマット名と start / stop の指定を最初に確認しておくのがおすすめです。バーコードまわりの細かな話はまだあるので、また機会があれば書いていければと思います。

コメント