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 上的倉庫:
上面 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è)正確的倉庫來引入并使用它:
這個(gè)庫是一個(gè)基于 ZXing 的 Android 二維碼解碼庫淫茵,使用起來還是非常簡(jiǎn)單的。
我把它 fork 回之后蹬跃,做了一些優(yōu)化和更新匙瘪,具體請(qǐng)查看下文。
快速使用:
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)断楷。
我做了修改之后的倉庫連接:
一直會(huì)持續(xù)更新它锨匆,需要的朋友保持關(guān)注吧~