Android ZXing(二維碼)庫全面使用解析

Android ZXing(二維碼)庫全面使用解析

本文原創(chuàng)败徊,轉(zhuǎn)載請(qǐng)注明出處。
歡迎關(guān)注我的 簡(jiǎn)書 铸董,關(guān)注我的專題 Android Class 我會(huì)長(zhǎng)期堅(jiān)持為大家收錄簡(jiǎn)書上高質(zhì)量的 Android 相關(guān)博文。

寫在前面:

春天到了,天氣轉(zhuǎn)暖习贫,風(fēng)吹走了北京的霧霾也帶來了困倦。每天感覺就是睡不醒千元、起不來苫昌。前一陣研究了 View 的體系,還差滑動(dòng)沖突和 View 的繪制沒有落筆成文幸海,還看了很多關(guān)于 MVP 這種代碼模式的文章祟身,未來爭(zhēng)取把它們都整理分享出來,便于記憶和交流物独。

不知不覺二維碼已經(jīng)深刻影響了我們的生活袜硫,為我們提供了極大的便利。線下付賬挡篓、租一輛單車婉陷、或者去要一個(gè)妹子的微信號(hào)等等。張小龍把它稱為從線下到線上的入口。正因?yàn)槎S碼如此的重要秽澳,并且出現(xiàn)的頻率越來越高世杀,所以 Android 應(yīng)用中掃面二維碼、條形碼的需求也很常見了肝集。本文就是來接入使用一個(gè)不錯(cuò)的二維碼庫 ZXing

二維碼是什么

在研究 ZXing 之前瞻坝,我一直好奇二維碼是根據(jù)什么生成的,并且最大能保存多少的信息杏瞻,去查閱了一下資料所刀,正好解決了我的疑問,在此介紹一下捞挥。

二維條碼是指在一維條碼(條形碼)的基礎(chǔ)上擴(kuò)展出另一維具有可讀性的條碼浮创,使用黑白矩形圖案表示二進(jìn)制數(shù)據(jù),被設(shè)備掃描后可獲取其中所包含的信息砌函。一維條碼的寬度記載著數(shù)據(jù)斩披,而其長(zhǎng)度沒有記載數(shù)據(jù)。二維條碼的長(zhǎng)度讹俊、寬度均記載著數(shù)據(jù)垦沉。二維條碼有一維條碼沒有的“定位點(diǎn)”和“容錯(cuò)機(jī)制”。容錯(cuò)機(jī)制在即使沒有辨識(shí)到全部的條碼仍劈、或是說條碼有污損時(shí)厕倍,也可以正確地還原條碼上的信息。二維條碼的種類很多贩疙,不同的機(jī)構(gòu)開發(fā)出的二維條碼具有不同的結(jié)構(gòu)以及編寫讹弯、讀取方法。

二維碼

總結(jié)起來就是二維碼是將有限的信息轉(zhuǎn)成二進(jìn)制这溅,并且表現(xiàn)為黑白矩陣圖组民,與一維的條形碼相比,二維碼擁有更好的容錯(cuò)能力悲靴。

ZXing

現(xiàn)在我們大概知道了二維碼是怎么生成的臭胜,有關(guān) Android 上掃碼的庫有很多,這次來介紹的是 ZXing对竣,一個(gè)出色的開源掃碼庫庇楞。

來看看它在 github 上的倉庫:

GitHub ZXing

上面 ReadMe 文件傳遞的信息大概就是 ZXing 是個(gè)很厲害的庫,支持各種平臺(tái)等等...然后又找了它一些相關(guān)的連接否纬,我發(fā)現(xiàn)有關(guān) Android 的信息少之又少吕晌,僅僅說了怎么引入,具體使用上沒說临燃,并且源碼中給出的 Android Module 代碼量有點(diǎn)多睛驳,掌握的成本太高烙心,總之當(dāng)時(shí)我覺得這個(gè)學(xué)習(xí)的姿勢(shì)不太對(duì)。

回到 google 重新搜索了一下 Android ZXing乏沸,終于找到了一個(gè)正確的倉庫來引入并使用它:

zxing-android-embedded

這個(gè)庫是一個(gè)基于 ZXing 的 Android 二維碼解碼庫淫茵,使用起來還是非常簡(jiǎn)單的。

我把它 fork 回之后蹬跃,做了一些優(yōu)化和更新匙瘪,具體請(qǐng)查看下文。

中文版 ZXing Android Embedded

快速使用:

new IntentIntegrator(this).initiateScan(); // `this` is the current Activity


// Get the results:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
    if(result != null) {
        if(result.getContents() == null) {
            Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
        }
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

可以看到使用起來非常便捷蝶缀,onActivityResult帶回掃碼出來的結(jié)果丹喻,然后進(jìn)行處理就OK了。下文中就不再介紹 ReadMe 中的內(nèi)容翁都,轉(zhuǎn)而介紹一下這個(gè)庫一些其他的配置碍论。

    protected Class<?> getDefaultCaptureActivity() {
        return CaptureActivity.class;
    }

一步步跟進(jìn) IntentIntegrator(this).initiateScan() 方法可以發(fā)現(xiàn),當(dāng)我不設(shè)置 CaptureActivity 時(shí)柄慰,調(diào)用默認(rèn)的 Activity 就是 CaptureActivity

所以對(duì)于吊起的掃碼 Activity 來說鳍悠,他的方向可以在 manifest 文件中的 android:screenOrientation 屬性直接指定:

        <activity
            android:name="com.journeyapps.barcodescanner.CaptureActivity"
            android:screenOrientation="landscape"
            tools:replace="screenOrientation" />

除了最基本的掃碼使用,再來看看他 IntentIntegrator 中其它的 setXXX 屬性吧坐搔。

  • integrator.setPrompt 在掃描頁面添加一個(gè)文字描述藏研,空字符串時(shí),可以取消顯示它薯蝎。

  • integrator.setOrientationLocked 設(shè)置是否鎖定掃碼 Activity 的方向遥倦。默認(rèn)為 true

  • integrator.setCameraId 設(shè)置使用攝像頭的 id,0 為后置攝像頭占锯,1 為前置攝像頭。這是系統(tǒng) CameraInfo 的屬性缩筛。

        /**
         * The facing of the camera is opposite to that of the screen.
         */
        public static final int CAMERA_FACING_BACK = 0;

        /**
         * The facing of the camera is the same as that of the screen.
         */
        public static final int CAMERA_FACING_FRONT = 1;
  • integrator.setBeepEnabled 設(shè)置掃描完成時(shí)是否允許“嘟嘟”的聲音消略。默認(rèn)為 true。源碼中的這個(gè)設(shè)置位于 BeepManager瞎抛,通過 MediaPlayer 播放了一段 .ogg 文件艺演。
播放的文件
  • integrator.setBarcodeImageEnabled 保存掃描完成后二維碼的圖像。源碼在這里:
    /**
     * Save the barcode image to a temporary file stored in the application's cache, and return its path.
     * Only does so if returnBarcodeImagePath is enabled.
     *
     * @param rawResult the BarcodeResult, must not be null
     * @return the path or null
     */
    private String getBarcodeImagePath(BarcodeResult rawResult) {
        String barcodeImagePath = null;
        if (returnBarcodeImagePath) {
            Bitmap bmp = rawResult.getBitmap();
            try {
                File bitmapFile = File.createTempFile("barcodeimage", ".jpg", activity.getCacheDir());
                FileOutputStream outputStream = new FileOutputStream(bitmapFile);
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                outputStream.close();
                barcodeImagePath = bitmapFile.getAbsolutePath();
            } catch (IOException e) {
                Log.w(TAG, "Unable to create temporary file and store bitmap! " + e);
            }
        }
        return barcodeImagePath;
    }
  • integrator.setDesiredBarcodeFormats 設(shè)置掃描的二維碼格式

  • integrator.setTimeout 設(shè)置一個(gè)超時(shí)時(shí)間桐臊,超過這個(gè)時(shí)間之后胎撤,掃描的 Activity 將會(huì)被 finish 。

自定義

通過昨天半天的時(shí)間断凶,算是把這個(gè)庫看明白了伤提,寫得很好值得推薦,有心的朋友可以好好看看源碼认烁,有的可學(xué)肿男。

項(xiàng)目中的需求各有不同介汹,所以在 UI 上可定制就成了很重要的一點(diǎn),這個(gè)庫雖然沒開放出很多方法舶沛,但是自定義起來依然自由方便嘹承,一起來看看姿勢(shì)吧。

  • integrator.setCaptureActivity 我們可以通過這個(gè)方法如庭,指定要傳入的自定義的掃描 Activity叹卷,那這個(gè) Activity 應(yīng)該怎么去定制呢?
    <com.journeyapps.barcodescanner.DecoratedBarcodeView
        android:id="@+id/zxing_barcode_scanner"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:zxing_scanner_layout="@layout/custom_barcode_scanner">
    </com.journeyapps.barcodescanner.DecoratedBarcodeView>

DecoratedBarcodeView 是掃描 View 的一個(gè)封裝類坪它,具體的 UI 屬性豪娜,在 app:zxing_scanner_layout="@layout/custom_barcode_scanner" 引入的 custom_barcode_scanner 布局文件中進(jìn)行定制修改。來看看這個(gè)布局:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
       xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.journeyapps.barcodescanner.BarcodeView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/zxing_barcode_surface"
        app:zxing_framing_rect_width="250dp"
        app:zxing_framing_rect_height="50dp"/>

    <com.journeyapps.barcodescanner.ViewfinderView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/zxing_viewfinder_view"
        app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
        app:zxing_result_view="@color/zxing_custom_result_view"
        app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
        app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>

    <TextView
        android:id="@+id/zxing_status_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:background="@color/zxing_transparent"
        android:text="@string/zxing_msg_default_status"
        android:textColor="@color/zxing_status_text"/>

</merge>
自定義掃描框

這個(gè)圖很直觀了吧哟楷,要是定制掃描線的顏色啊瘤载,或者掃描框的大小啊,都沒有問題了~

當(dāng)然我把它 fork 回來之后卖擅,做了一些改動(dòng)鸣奔,比如修了兩個(gè) bug,然后開放了兩個(gè)我認(rèn)為比較合適的新的設(shè)置項(xiàng):

  • setBeepResource 讓掃描之后發(fā)出的嘟嘟聲可定制惩阶,需要傳入本地的一個(gè) raw 文件挎狸。

  • setVibrateEnable 設(shè)置掃描完成之后,是否讓手機(jī)震動(dòng)断楷。

我做了修改之后的倉庫連接:

ZXing Android Embedded

一直會(huì)持續(xù)更新它锨匆,需要的朋友保持關(guān)注吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冬筒,隨后出現(xiàn)的幾起案子恐锣,更是在濱河造成了極大的恐慌,老刑警劉巖舞痰,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件土榴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡响牛,警方通過查閱死者的電腦和手機(jī)玷禽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呀打,“玉大人矢赁,你說我怎么就攤上這事”岽裕” “怎么了撩银?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)瘫寝。 經(jīng)常有香客問我蜒蕾,道長(zhǎng)稠炬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任咪啡,我火速辦了婚禮首启,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撤摸。我一直安慰自己毅桃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布准夷。 她就那樣靜靜地躺著钥飞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衫嵌。 梳的紋絲不亂的頭發(fā)上读宙,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天,我揣著相機(jī)與錄音楔绞,去河邊找鬼结闸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛酒朵,可吹牛的內(nèi)容都是我干的桦锄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼蔫耽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼结耀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起匙铡,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤图甜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后慰枕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體具则,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年具帮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片低斋。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜂厅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膊畴,到底是詐尸還是另有隱情掘猿,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布唇跨,位于F島的核電站稠通,受9級(jí)特大地震影響衬衬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜改橘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一滋尉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧飞主,春花似錦狮惜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筏餐,卻和暖如春开泽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背魁瞪。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工穆律, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佩番。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓众旗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親趟畏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贡歧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容