Android中的二維碼生成與掃描功能
0. 前言
今天這篇文章主要描述二維碼的生成與掃描,使用目前流行的Zxing,為什么要講二維碼,因為二維碼太普遍了,隨便一個Android APP都會有二維碼掃描。本篇旨在幫助有需求的同學快速完成二維碼生成和掃描的功能。
1. Zxing的使用
從github上下載項目后,可以看到整體代碼結(jié)構(gòu)如下:

我們只需將Zxing包下的所有代碼copy一份到我們的項目中去,除了這些還需要zxing的jar包,最后相應的資源文件,包括values文件下的ids文件、raw文件中的資源文件(可以替換)、layout文件下的activity_capture.xml(可以進行相應的訂制) 和圖片資源。
2. 生成二維碼的實現(xiàn)
等上面工作全部準備完畢后,就可以創(chuàng)建我們的二維碼了。如何生成二維碼?
需要EncodingUtils這個二維碼生成工具類。通過調(diào)用工具類中的createQRCode()方法來生成二維碼。該方法參數(shù)介紹如下:
/* * content:二維碼內(nèi)容 * widthPix:二維碼寬度 * heightPix:二維碼高度 * logoBm:二維碼中間的logo對應的Bitmap */ public static Bitmap createQRCode(String content, int widthPix, int heightPix, Bitmap logoBm)
下面完成的是生成的一個百度地址的二維碼,中間LOGO是Android小機器人。并保存圖片到本地,方便后續(xù)測試二維碼的本地讀取功能。
/**
* 創(chuàng)建、展示二維碼并將bitmap保存在本地
*/
private void create() {
int width = DensityUtil.dip2px(this, 200);
Bitmap bitmap = EncodingUtils.createQRCode("http://www.baidu.com",
width, width, BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher));
iv_zxing.setImageBitmap(bitmap);
saveBitmap(bitmap);
}
/**
* 將Bitmap保存在本地
*
* @param bitmap
*/
public void saveBitmap(Bitmap bitmap) {
// 首先保存圖片
File appDir = new File(Environment.getExternalStorageDirectory(),"zxing_image");
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = "zxing_image" + ".jpg";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
// 把文件插入到系統(tǒng)圖庫
try {
MediaStore.Images.Media.insertImage(this.getContentResolver(),file.getAbsolutePath(), fileName, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 通知圖庫更新
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + "/sdcard/namecard/")));
}
看到如下效果:

3. 讀取二維碼的實現(xiàn)
3.1 攝像頭掃描的方式
二維碼掃描需要借助于CaptureActivity這個類,打開CaptureActivity界面并進行掃描,掃描完畢后回調(diào)onActivityResult()方法,從onActivityResult()中得到掃描后的結(jié)果。效果就不演示的,因為使用的是模擬器。詳細代碼如下:
/**
* 打開二維碼掃描
*/
private void open() {
config();
startActivityForResult(new Intent(MainActivity.this,CaptureActivity.class), 0);
}
/**
* 提高屏幕亮度
*/
private void config() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = 1.0f;
getWindow().setAttributes(lp);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String result = bundle.getString("result");
tv_result.setText(result);
}
3.2 本地圖片掃描的方式
掃描本地圖片需要我們在CaptureActivity中進行相應的修改,為此我在掃描界面底部增加了一個按鈕,用來選擇本地圖片。layout代碼這里就不展示,我們直接看點擊后的事件處理。
/**
* 打開本地圖片
*/
private void openLocalImage() {
// 打開手機中的相冊
Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);
innerIntent.setType("image/*");
Intent wrapperIntent = Intent.createChooser(innerIntent, "選擇二維碼圖片");
this.startActivityForResult(wrapperIntent, 0x01);
}
打開系統(tǒng)圖片庫后選擇圖片,這時需要重寫onActivityResult()方法用于返回圖片信息。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 0x01:
// 獲取選中圖片的路徑
Cursor cursor = getContentResolver().query(data.getData(),null, null, null, null);
if (cursor.moveToFirst()) {
photo_path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
new Thread(new Runnable() {
@Override
public void run() {
Result result = scanningImage(photo_path);
if (result != null) {
handleDecode(result, new Bundle());
}
}
}).start();
break;
}
}
}
獲取圖片路徑photo_path后,調(diào)用scanningImage()方法進行掃描,Zxing源碼中,掃描到的結(jié)果都是存放在Result結(jié)果集中。獲取到Result后,就進行結(jié)果的回傳,閱讀CaptureActivity源碼可以得知最后Result結(jié)果集會傳遞給handleDecode()方法。
/**
* A valid barcode has been found, so give an indication of success and show
* the results.
*
* @param rawResult
* The contents of the barcode.
* @param bundle
* The extras
*/
public void handleDecode(Result rawResult, Bundle bundle) {
inactivityTimer.onActivity();
beepManager.playBeepSoundAndVibrate();
Intent resultIntent = new Intent();
bundle.putInt("width", mCropRect.width());
bundle.putInt("height", mCropRect.height());
bundle.putString("result", rawResult.getText());
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
CaptureActivity.this.finish();
}
獲取到圖片路徑后需要將其二維碼信息包裝成Result對象,因此需要解析圖片:
/**
* 掃描二維碼圖片的方法
*
* @param path
* @return
*/
public Result scanningImage(String path) {
if (TextUtils.isEmpty(path)) {
return null;
}
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF8"); // 設置二維碼內(nèi)容的編碼
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先獲取原大小
scanBitmap = BitmapFactory.decodeFile(path, options);
options.inJustDecodeBounds = false; // 獲取新的大小
int sampleSize = (int) (options.outHeight / (float) 200);
if (sampleSize <= 0)
sampleSize = 1;
options.inSampleSize = sampleSize;
scanBitmap = BitmapFactory.decodeFile(path, options);
int width = scanBitmap.getWidth();
int height = scanBitmap.getHeight();
int[] pixels = new int[width * height];
scanBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
/**
* 第三個參數(shù)是圖片的像素
*/
RGBLuminanceSource source = new RGBLuminanceSource(width, height,
pixels);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
return reader.decode(bitmap1, hints);
} catch (NotFoundException e) {
e.printStackTrace();
} catch (ChecksumException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
return null;
}
根據(jù)路徑獲取Bitmap,最后通過QRCodeReader 中的decode方法解析成Result對象并返回,最終傳遞給handleDecode方法。運行程序效果如下,掃描出來的是之前定義的百度地址。

最后不要忘了申明權(quán)限和CaptureActivity。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.VIBRATE"/> <activity android:name="com.example.zxingtest.zxing.activity.CaptureActivity"/>
大家可以參考下這篇文章:Android實現(xiàn)二維碼掃描和生成的簡單方法
以上所述是小編給大家介紹的Android中的二維碼生成與掃描功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
Android 關于ExpandableListView去掉里頭分割線的方法
下面小編就為大家?guī)硪黄狝ndroid 關于ExpandableListView去掉里頭分割線的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
Android通過自定義Activity實現(xiàn)懸浮的Dialog詳解
這篇文章主要給大家介紹了關于Android通過自定義Activity實現(xiàn)懸浮的Dialog的相關資料,文中給出了詳細的示例代碼供大家參考學習,對大家具有一定的參考學習價值,感興趣的朋友們下面來一起看看吧。2017-05-05
解決webview 第二次調(diào)用loadUrl頁面不刷新的問題
這篇文章主要介紹了解決webview 第二次調(diào)用loadUrl頁面不刷新的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03

