您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關如何使用Android實現基于ZXing快速集成二維碼掃描功能的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
二維碼掃描現在是一直比較多的應用場景,android的開源項目ZXing提供了完整、成熟的解決方案,如果僅僅是出于快速開發的目的,可以根據自己的項目需要,把ZXing官方提供的項目稍加裁剪,就可以快速的集成到自己的項目中。下面詳細演示和介紹如何實現基于ZXing官方提供的源碼,快速集成二維碼掃描功能到自己項目中的解決方案。
(第1步):到ZXing官方主頁下載最新的項目代碼包,ZXing在github的官方主頁:https://github.com/zxing,下載后解壓。解壓后根目錄下有若干項目目錄,其中的:android就是我們需要的項目,把它導入到Eclispse中。
(第2步):ZXing的Android項目需要引用兩個關鍵的庫文件:android-core-x.x.x.jar和 core-x.x.x.jar,其中x.x.x表示版本號。截止發表本博文時候,版本已經是3.2.0了。這兩個關鍵的android-core-x.x.x.jar 和 core-x.x.x.jar 文件,實際上都可以從第一步下載得到的源代碼中自己編譯生成,網上也有編譯的具體方案,但簡單期間,也可以從ZXing的官方直接下載已經編譯好的文件,其中android-core的下載鏈接是:http://repo1.maven.org/maven2/com/google/zxing/android-core/,另外一個ZXing的core下載鏈接是:http://repo1.maven.org/maven2/com/google/zxing/core/ ,選擇最新版本的庫文件或者自己需要的版本號,下載后,和其他android項目中導入庫文件類似,導入到Android項目中的libs目錄下,如果沒有libs,新建一個名為libs的目錄,把兩個庫文件放進去即可。
(第3步):這一步作為演示,我們自己新建一個MainActiviy,作為項目的啟動器Activity,App將啟動我們自己的MainActivity。觀察ZXing官方提供的AndroidManifest.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright (C) 2008 ZXing authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.zxing.client.android" android:versionName="4.7.3" android:versionCode="103" android:installLocation="auto"> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.FLASHLIGHT"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="21"/> <!-- Don't require camera, as this requires a rear camera. This allows it to work on the Nexus 7 --> <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera.front" android:required="false"/> <!-- TODO replace above two with next line after Android 4.2 --> <!-- <uses-feature android:name="android.hardware.camera.any"/> --> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/> <uses-feature android:name="android.hardware.camera.flash" android:required="false"/> <uses-feature android:name="android.hardware.screen.landscape"/> <uses-feature android:name="android.hardware.wifi" android:required="false"/> <!-- This excludes Google TV, which is unfortunately included by virtue of not requiring a camera --> <uses-feature android:name="android.hardware.touchscreen"/> <!-- TODO make this not required again after android.hardware.camera.any is available --> <supports-screens android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:anyDensity="true"/> <application android:icon="@drawable/launcher_icon" android:logo="@drawable/launcher_icon" android:label="@string/app_name" android:allowBackup="true"> <activity android:name=".CaptureActivity" android:screenOrientation="sensorLandscape" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/CaptureTheme" android:windowSoftInputMode="stateAlwaysHidden"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <action android:name="com.google.zxing.client.android.SCAN"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="zxing.appspot.com" android:path="/scan"/> </intent-filter> <!-- We also support a Google Product Search URL. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="www.google.com" android:path="/m/products/scan"/> </intent-filter> <!-- And the UK version. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="www.google.co.uk" android:path="/m/products/scan"/> </intent-filter> <!-- Support zxing://scan/?... like iPhone app --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="zxing" android:host="scan" android:path="/"/> </intent-filter> </activity> <activity android:name=".PreferencesActivity" android:label="@string/preferences_name" android:stateNotNeeded="true"/> <activity android:name=".encode.EncodeActivity" android:stateNotNeeded="true"> <intent-filter> <action android:name="com.google.zxing.client.android.ENCODE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <!-- This allows us to handle the Share button in Contacts. --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/x-vcard"/> </intent-filter> <!-- This allows us to handle sharing any plain text . --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity> <activity android:name=".book.SearchBookContentsActivity" android:label="@string/sbc_name" android:stateNotNeeded="true" android:screenOrientation="sensorLandscape"> <intent-filter> <action android:name="com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".share.ShareActivity" android:stateNotNeeded="true" android:screenOrientation="user"> <intent-filter> <action android:name="com.google.zxing.client.android.SHARE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".history.HistoryActivity" android:label="@string/history_title" android:stateNotNeeded="true"/> <activity android:name=".share.BookmarkPickerActivity" android:label="@string/bookmark_picker_name" android:stateNotNeeded="true"/> <activity android:name=".share.AppPickerActivity" android:label="@string/app_picker_name" android:stateNotNeeded="true"/> <activity android:name=".HelpActivity" android:label="@string/menu_help" android:screenOrientation="user" android:stateNotNeeded="true"/> </application> </manifest>
其實ZXing官方的項目已經作為為第三方提供集成的代碼了,比如其中的關鍵Activity:.\src\com\google\zxing\client\android\CaptureActivity.Java,在聲明中已經提供好了從各種入口訪問的Intent的Action。所以在我們自己新建的MainActivity中,直接隱式指定一個Intent的Action,啟動之即可:
package com.google.zxing.client.android; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.Toast; public class MainActivity extends Activity { private final int REQUEST_CODE = 0xa1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = new Intent(); //隱式指定 intent.setAction("com.google.zxing.client.android.SCAN"); //啟動ZXing已經寫好、且我們做小量修改后的CaptureActivity。 startActivityForResult(intent, REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //我們需要的結果返回 if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { //result就是二維碼掃描的結果。 String result = data.getStringExtra("RESULT"); Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT) .show(); } } }
因為我們啟動ZXing的CaptureActivity不是目的,真正的目的是啟動ZXing的CaptureActivity獲得二維碼掃描結果,因此以startActivityForResult()的方式啟動。相應的,我們需要重寫:protected void onActivityResult(int requestCode, int resultCode, Intent data),以回調等待傳回結果。
(第4步):這一步是重點。在.\src\com\google\zxing\client\android\目錄下的CaptureActivity.java中的方法: public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor);此方法是一個回調函數。ZXing項目中寫好的掃描模塊掃描后返回回調此方法,ZXing官方的原始 public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor)方法是這樣的:
/** * A valid barcode has been found, so give an indication of success and show the results. * * @param rawResult The contents of the barcode. * @param scaleFactor amount by which thumbnail was scaled * @param barcode A greyscale bitmap of the camera data which was decoded. */ public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) { inactivityTimer.onActivity(); lastResult = rawResult; ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); boolean fromLiveScan = barcode != null; if (fromLiveScan) { historyManager.addHistoryItem(rawResult, resultHandler); // Then not from history, so beep/vibrate and we have an image to draw on beepManager.playBeepSoundAndVibrate(); drawResultPoints(barcode, scaleFactor, rawResult); } switch (source) { case NATIVE_APP_INTENT: case PRODUCT_SEARCH_LINK: handleDecodeExternally(rawResult, resultHandler, barcode); break; case ZXING_LINK: if (scanFromWebPageManager == null || !scanFromWebPageManager.isScanFromWebPage()) { handleDecodeInternally(rawResult, resultHandler, barcode); } else { handleDecodeExternally(rawResult, resultHandler, barcode); } break; case NONE: SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (fromLiveScan && prefs.getBoolean(PreferencesActivity.KEY_BULK_MODE, false)) { Toast.makeText(getApplicationContext(), getResources().getString(R.string.msg_bulk_mode_scanned) + " (" + rawResult.getText() + ')', Toast.LENGTH_SHORT).show(); // Wait a moment or else it will scan the same barcode continuously about 3 times restartPreviewAfterDelay(BULK_MODE_SCAN_DELAY_MS); } else { handleDecodeInternally(rawResult, resultHandler, barcode); } break; } }
我們將精簡此方法,定制自己所需要的內容,為滿足我們自己項目中的需求,把此方法修改后的代碼為:
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) { inactivityTimer.onActivity(); lastResult = rawResult; ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); boolean fromLiveScan = barcode != null; if (fromLiveScan) { historyManager.addHistoryItem(rawResult, resultHandler); // Then not from history, so beep/vibrate and we have an image to draw on beepManager.playBeepSoundAndVibrate(); drawResultPoints(barcode, scaleFactor, rawResult); } //在這里增加我們的代碼,目的是:做最小量的修改,僅僅把ZXing提供的CaptureActivity作為一個中間使用的Activity集成到我們自己的項目。 //啟動實現二維碼掃描,返回一個結果就可以了。 //然后結束這個Activity。 Intent intent=new Intent(); //<key,value>形式存儲二維碼結果。 //rawResult.getText()即為二維碼結果。 intent.putExtra("RESULT", rawResult.getText()); this.setResult(Activity.RESULT_OK, intent); this.finish(); /** 以下是ZXing提供的源碼,根據項目需要可以刪減使用。 簡單期間,我們只需要二維碼掃描后返回一個掃描的字符串結果。 所以在次暫時注釋掉。 switch (source) { case NATIVE_APP_INTENT: case PRODUCT_SEARCH_LINK: handleDecodeExternally(rawResult, resultHandler, barcode); break; case ZXING_LINK: if (scanFromWebPageManager == null || !scanFromWebPageManager.isScanFromWebPage()) { handleDecodeInternally(rawResult, resultHandler, barcode); } else { handleDecodeExternally(rawResult, resultHandler, barcode); } break; case NONE: SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (fromLiveScan && prefs.getBoolean(PreferencesActivity.KEY_BULK_MODE, false)) { Toast.makeText(getApplicationContext(), getResources().getString(R.string.msg_bulk_mode_scanned) + " (" + rawResult.getText() + ')', Toast.LENGTH_SHORT).show(); // Wait a moment or else it will scan the same barcode continuously about 3 times restartPreviewAfterDelay(BULK_MODE_SCAN_DELAY_MS); } else { handleDecodeInternally(rawResult, resultHandler, barcode); } break; } **/ }
(第5步):這一步比較簡單,是剩余的收尾工作,修改AndroidManifest.xml文件,把我們的MainActivity作為主Activity啟動。把ZXing的CaptureActivity作為一個普通的Activity。
修改后的AndroidManifest.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright (C) 2008 ZXing authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.zxing.client.android" android:versionName="4.7.3" android:versionCode="103" android:installLocation="auto"> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.FLASHLIGHT"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="21"/> <!-- Don't require camera, as this requires a rear camera. This allows it to work on the Nexus 7 --> <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera.front" android:required="false"/> <!-- TODO replace above two with next line after Android 4.2 --> <!-- <uses-feature android:name="android.hardware.camera.any"/> --> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/> <uses-feature android:name="android.hardware.camera.flash" android:required="false"/> <uses-feature android:name="android.hardware.screen.landscape"/> <uses-feature android:name="android.hardware.wifi" android:required="false"/> <!-- This excludes Google TV, which is unfortunately included by virtue of not requiring a camera --> <uses-feature android:name="android.hardware.touchscreen"/> <!-- TODO make this not required again after android.hardware.camera.any is available --> <supports-screens android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:anyDensity="true"/> <application android:icon="@drawable/launcher_icon" android:logo="@drawable/launcher_icon" android:label="@string/app_name" android:allowBackup="true"> <!-- 新增的我們自己的MainActiviy作為啟動Activity --> <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".CaptureActivity" android:screenOrientation="sensorLandscape" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/CaptureTheme" android:windowSoftInputMode="stateAlwaysHidden"> <!-- 把ZXing官方提供的作為 main activity啟動的CaptureActivity作為一個普通Activiy。 <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> --> <intent-filter> <action android:name="com.google.zxing.client.android.SCAN"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="zxing.appspot.com" android:path="/scan"/> </intent-filter> <!-- We also support a Google Product Search URL. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="www.google.com" android:path="/m/products/scan"/> </intent-filter> <!-- And the UK version. --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="www.google.co.uk" android:path="/m/products/scan"/> </intent-filter> <!-- Support zxing://scan/?... like iPhone app --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="zxing" android:host="scan" android:path="/"/> </intent-filter> </activity> <activity android:name=".PreferencesActivity" android:label="@string/preferences_name" android:stateNotNeeded="true"/> <activity android:name=".encode.EncodeActivity" android:stateNotNeeded="true"> <intent-filter> <action android:name="com.google.zxing.client.android.ENCODE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <!-- This allows us to handle the Share button in Contacts. --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/x-vcard"/> </intent-filter> <!-- This allows us to handle sharing any plain text . --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity> <activity android:name=".book.SearchBookContentsActivity" android:label="@string/sbc_name" android:stateNotNeeded="true" android:screenOrientation="sensorLandscape"> <intent-filter> <action android:name="com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".share.ShareActivity" android:stateNotNeeded="true" android:screenOrientation="user"> <intent-filter> <action android:name="com.google.zxing.client.android.SHARE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".history.HistoryActivity" android:label="@string/history_title" android:stateNotNeeded="true"/> <activity android:name=".share.BookmarkPickerActivity" android:label="@string/bookmark_picker_name" android:stateNotNeeded="true"/> <activity android:name=".share.AppPickerActivity" android:label="@string/app_picker_name" android:stateNotNeeded="true"/> <activity android:name=".HelpActivity" android:label="@string/menu_help" android:screenOrientation="user" android:stateNotNeeded="true"/> </application> </manifest>
備注:此文僅僅是最簡單的一個示例,演示了如何在自己的項目中在ZXing官方項目已提供的完整代碼基礎上,做最小量的改動,將二維碼掃描功能快速集成到自己的項目中為我所用,若需要更多的細節調整,則需要深入定制和改編源代碼。
感謝各位的閱讀!關于“如何使用Android實現基于ZXing快速集成二維碼掃描功能”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。