如何在Android系統上使用zBar來實現條碼掃描?


在生活中常常可以看到條碼(Barcode)的存在,無論是商品結帳時在收銀台使用的EAN條碼、書籍使用的ISBN條碼,還是在最近因行動裝置的流行也跟著帶動起來的QR Code,這些條碼都可以讓我們的生活更便利,傳遞資訊的速度更快,省下許多使用鍵盤打字的時間。大多數的Android裝置,都有配備相機(Camera)功能,因此可以直接使用Android相機功能來拍攝出條碼的樣子,再使用一些影像處理的演算法來解析出條碼的內容。在Android上最常用來辨識條碼影像的工具,應該是使用純Java語言的zxing開源專案,因為不需要動用到C/C++層的Native Code,所以應用起來十分容易。但是使用Java的話,就會有效能不好的缺點,因此,這篇文章將提供另一個選擇,也就是使用以C語言為基礎的zBar來完成條碼辨識

zBar

zBar可以支援的條碼有EAN-8、EAN-13、UPC-E、UPC-A、ISBN-10、ISBN-13、Interleaved 2 of 5(交錯式25條碼)、DataBar、DataBar Expanded、Codabar、Code 39、Code 93、Code 128、PDF417、QR Code開源專案網址如下:

http://sourceforge.net/projects/zbar/

官方已經有提供編譯好的Android SDK,可以直接下載下來,將.so檔和.jar檔案加入Android專案中的「libs」資料夾即可使用。只是如果直接這樣用的話,可能會遭遇到很多問題,最常見的就是文字亂碼的問題,亂碼問題與zBar預設的字元編碼以及使用到的libiconv版本有關。因此建議如果要使用zBar的話,還是自己使用JNIAndroid NDK來編譯出最新的版本吧!

編譯zBar For Android

編譯環境:Linux Mint 17 MATE

取得zBar

zBar的原始碼可以直接在zBar的SourceForge上取得。只是要注意的是,最好不要使用官方打包好、正式發佈的zBar版本,版本可能過舊,能夠解析的條碼種類也會比較少。所以建議將zBar目前最新的專案資料夾整個打包下載回來。

取得libiconv

zBar可以使用libiconv來協助進行編碼的預測與轉換,libiconv開源專案網址如下:

https://www.gnu.org/software/libiconv/

加入JNI支援至Android 專案

在編譯zBar For Android時,會使用到JNI,所以要讓Android專案能支援JNI。如果您還不知道怎麼樣加入JNIAndroid專案中,可以參考這篇文章:

https://magiclen.org/android-jni/

如何在Android系統上使用zBar來實現條碼掃描?

zBarlibiconv原始碼放置於Android專案下

把剛才下載下來的zBarlibiconv原始碼目錄放置在Android的專案下,為了要讓.mk設定檔能直接套用,需分別命名成「zbarSDK-master」和「libiconv」。

如何在Android系統上使用zBar來實現條碼掃描?

加入Android.mk和Application.mk至JNI目錄

在官方的zBar專案中有這兩個檔案可以在「android/jni」目錄下找到,但是編譯時Android.mk檔案內的路徑還要另外設置,於是筆者稍微將它修改了一下。下載網址:

//file.magiclen.org/index.php?file=7a6261722d6d6b2e726172

配置libiconv

將終端機的工作目錄移動到libiconv目錄下,執行以下指令來配置libiconv的編譯設定:

./configure

如何在Android系統上使用zBar來實現條碼掃描?

如何在Android系統上使用zBar來實現條碼掃描?

使用ndk-build來編譯

將終端機下的工作目錄移動到Android專案的目錄下,執行以下指令使用Android NDK開始編譯libiconvzbar

ndk-build

如何在Android系統上使用zBar來實現條碼掃描?

編譯成功的話可以看到以下畫面:

如何在Android系統上使用zBar來實現條碼掃描?

並且可以在「libs」目錄中找到編譯出來的.so檔案。

如何在Android系統上使用zBar來實現條碼掃描?

然而,現實總是不會如此順利。如果編譯過程有問題發生,請繼續按照以下方式修改。

找不到langinfo.h

編譯時若是出現localcharset.c找不到langinfo.h的訊息,如下圖:

如何在Android系統上使用zBar來實現條碼掃描?

要修改libiconv目錄下,「libcharset」目錄裡的「config.h」檔案,將「HAVE_LANGINFO_CODESET」這個巨集設為「0」。

如何在Android系統上使用zBar來實現條碼掃描?

如何在Android系統上使用zBar來實現條碼掃描?

c」變數沒有宣告

編譯時若是出現localcharset.c中「'c' undeclared」的訊息,如下圖:

如何在Android系統上使用zBar來實現條碼掃描?

要修改libiconv目錄下,「libcharset/lib」目錄裡的「localcharset.c」檔案,在發生未宣告「c」錯誤的那行程式碼前,加上「int c;」宣告出「c」變數即可。

如何在Android系統上使用zBar來實現條碼掃描?

如何在Android系統上使用zBar來實現條碼掃描?

如何在Android系統上使用zBar來實現條碼掃描?

編譯成功,但在執行時,libiconv.so的「__ctype_get_mb_cur_max」會出錯

這似乎是NDK的BUG,在stdlib.h內有宣告出__ctype_get_mb_cur_max函數,但是卻沒有去實作它。如果出現這個問題,不建議直接修改NDK,要到libiconv目錄下,修改「libcharset/lib」目錄裡的「localcharset.c」檔案,在檔案最下面加上以下程式碼即可。

使用zBar For Android

編譯出zBar的.so檔之後,要如何在Android SDK下使用呢?還要透過JNI嗎?不用,我們其實已經在Android.mk檔配置中將JNI的程式編譯進.so檔中了,因此只要在Android SDKJava程式中讀入.so函式庫,並宣告出Native的方法,即可使用zBar的功能。這部份的程式在zBar目錄下的「java」目錄中可以找到,只要將程式碼加到Android專案中的「src」目錄下就可以使用。

如何在Android系統上使用zBar來實現條碼掃描?

如何在Android系統上使用zBar來實現條碼掃描?

至於用法的話,就參考一下zBar目錄下的「android」目錄裡的範例吧!

解決zBar讀取QR Code會有亂碼的問題

讀取QR Code會有亂碼並不是zBar的問題,而是QR Code並沒有統一的字元編碼方式,許多人常會使用內碼來產生QR Code,如果在讀取QR Code時不知道當初這個QR Code是以何種方式編碼字元的話,那就沒辦法正常地將字元解碼還原。zBar能夠做到的,最多只是「猜」這個QR Code是用什麼編碼而已。如果要控制zBarQR Code編碼的方式的話,可以修改zBar目錄下「zbar/qrcode」中的「qrdectxt.c」檔案。

如何在Android系統上使用zBar來實現條碼掃描?

enc_list陣列的大小和順序,就是猜測編碼的種類數量和猜測順序。修改一下,讓它能符合自己的需求吧!

如何在Android系統上使用zBar來實現條碼掃描?

關於作者

Magic Len

各位好,我是Magic Len,是這網站的管理員。我是台灣台中大肚山上人,畢業於台中高工資訊科和台灣科技大學資訊工程系,曾在桃機航警局服役。我熱愛自然也熱愛科學,喜歡和別人分享自己的知識與經驗。如果你有興趣認識我,可以加我的Facebook,並且請註明是從MagicLen來的。

相關文章