導讀
- 雖然有句話在程序員中說:”別人造好的輪子,不要重複發明輪子”,但是隻會用別人的東西,對自己個人技術的提升也是不可能的0.0 那麼最好的方式就是看源碼.
- 本篇文章就是個人在使用ZXing後看官方Demo源碼的讀後感,有不對的地方歡迎評論指出,一起討論.
源碼操作:
官方源碼Demo結構圖:
由圖可知官方Demo裏面有兩個項目:
1. CaptureActivity 官方的”二維碼掃描器”項目
2. ZXingTestActivity 測試CaptureActivity用的,有興趣的同學自己看下,以後有時間再補充
com.google.zxing.client.android 包
與CaptureActivity直接相關的核心組件。包含了發生震動管理器,閃光燈等等
- AmbientLightManager implements SensorEventListener 光線管理器(環境光亮屏幕自動變暗,反之)
使用 (當我們閃光燈模式選擇自動時會調用):
1. CaptureActivity onCreate() 實例化AmbientLightManager ambientLightManager = new AmbientLightManager(this);
2. 在要使用的方法啓動ambientLightManager.start(cameraManager)或關閉ambientLightManager.start()
- BeepManager implements MediaPlayer.OnErrorListener, Closeable 掃描成功後的手機震動和提示音管理器
使用:
1. CaptureActivity onCreate() 中 BeepManager beepManager = new BeepManager(this);
2. CaptureActivity onResume() 中 beepManager.updatePrefs();
3. CaptureActivity onPause() 中 beepManager.close();
4. 在要使用的方法啓動 beepManager.playBeepSoundAndVibrate();
CaptureActivity “條形碼掃描器”主頁面,主要邏輯
CaptureActivityHandler 消息處理類
幾個消息說明:
1. DecodeHandler 的 decode_succeeded 解碼成功
2. DecodeHandler 的 decode_failed 解碼失敗
3. CaptureActivity 的 restart_preview 啓動掃描
4. CaptureActivity 的 return_scan_result 返回條形碼結果內容界面
5. CaptureActivity 的 launch_product_query 查詢商品(打開瀏覽器)
Contents 常量類(掃碼類型)
DecodeFormatManger 配置”解碼類型”管理類:
主要方法:
通過parseDecodeFormats() ,返回我們掃描後得到的 “解碼格式” (一維碼,二維碼,其他)
1. DecodeFormatManager.parseDecodeFormats(intent);
2. DecodeFormatManager.parseDecodeFormats(inputUri);
- DecodeHandler 解碼消息處理類:
主要方法:
DecodeHandler.decode(byte[] data, int width, int height) 解碼取景器矩形中的數據以及所需時間 解碼的核心類
DecodeHandler類被DececodeThread線程中實例化 Handler handler = new DecodeHandler(activity, hints);
- DecodeHintManager 解碼線索管理類 (根據傳進來的參數(Uri,intent),返回線索)
小說明:
1. “hints 線索”: 用於通過條形碼閱讀器,更快或準確的解碼
2. 傳線索給 CaptrueActivity ,交給DecodeThread 處理主要方法 (在CaptureActivity onResume() 中被調用):
1. DecodeHintManager.parseDecodeHints(intent);
2. decodeHints = DecodeHintManager.parseDecodeHints(inputUri);
- DecodeThread 這個線程處理所有圖像的解碼
主要處理從 CaptureActivity 拿到的hints 線索
- FinishListenr implements DialogInterface.OnClickListener,DialogInterface.OnCancelListener
Dialog 監聽器(用於出現bug時退出Activity)
*使用:(結合 AlertDialog.Builder)*
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage(getString(R.string.msg_camera_framework_bug));
builder.setPositiveButton(R.string.button_ok, new FinishListener(this));
builder.setOnCancelListener(new FinishListener(this));
builder.show();
HelpActivity 幫助頁面(webView查看幫助文檔)
HttpHelper 網絡請求工具類:
小說明:
1. HttpConnection 安全的網絡請求(處理了可能出現的異常)
2. 訪問特定的主機名或者以外的主機名
3. 能請求不同的網絡數據類型 (html,xml,json,text)
4. 請求數據成功,把數據存到StringBuilder 緩衝區主要方法(搜索圖書資源用):
1. downloadViaHttp(String uri, ContentType type) 下載全部資源
2. downloadViaHttp(String uri, ContentType type, int maxChars) 下載自定大小資源
3. unredirect(Uri uri) 未定向訪問網絡 (如果訪問的uri不包含上面的Host,就訪問默認的uri)
使用:
CharSequence content = HttpHelper.downloadViaHttp(uri,HttpHelper.ContentType.JSON);
如:
HttpHelper.downloadViaHttp("https://www.googleapis.com/books/v1/volues?q=isbn:" + isbn,HttpHelper.ContentType.JSON);
- InactivityTimer 一段時間不操作(5分鐘 ),關閉該應用(工具類)
使用在生命週期方法中:
1. 在onCreate() 初始化該對象 InactivityTimer = new InactivityTimer(this);
2. 在onResume() ; inactivityTimer.onResume()
3. 在onPause() ; inactivityTimer.onPause();
4. 在onDestroy() ; inactivityTimer.shutdown();
5. 在處理解碼的handleDecode() 初始化該方法 ; inactivityTimer.onActivity() 啓動裏面的線程方法,讓應用在解碼時不執行InactivityTimer
Intents 這個類提供了在發送條形碼掃描器的意圖所使用的常量。
IntentSource 枚舉類
1. NATIVE_APP_INTENT
本地app向條碼掃描器(Barcode Scanner)發起的啓動指令
* 比如在androidtest項目中,利用整合的android-integration對條碼掃描器發起調用指令
* :com.google.zxing.client.android.SCAN
* 條碼掃描器中該啓動命令對應的Source類型便是NATIVE_APP_INTENT
2. PRODUCT_SEARCH_LINK , ZXING_LINK
打開條碼掃描器的時候傳入查詢商品的url,與最終掃描到的product id結合進行查詢 兩種url的形式不同
3. NONE
直接打開條碼掃描器
LocaleManager 處理任何特定地區的設備邏輯(適配設備語言的工具類)
PreferencesActivity “設置”裏面的一些常量
用PreferencesFragment replace PreferencesActivity
PreferencesFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener “設置”頁面實現
- 佈局在 res/xml/Preferences
- 一般結合PreferencesActivity 一起使用
- 裏面有很多的Preference對象調用
- “自定義搜索網址”單獨實現
- “條碼類型”,設置幾個雙選框選項,最少選擇一項
- ScanFromWebPageManager 工具類:
傳一個html的url,通過佔位符{CODE},{RAWCODE},{META},{FORMAT},{TYPE}返回一個對應的,我們能處理的url
1. 讓我們可以從一個網頁調用ZXing進行掃描,通過回調URL的方式,返回結果到我們的網站
2. 如掃到 01234,鏈接到 http://foo.com/products/01234/description 網頁
3. {CODE}是一種返回代碼值的佔位符
ViewfinderView SurferView相機預覽界面(取景器矩形和部分透明,激光掃描儀點動畫和結果)
ViewfinderResultPointCallback SurferView相機預覽回調
com.google.zxing.client.android.book 包
如果查詢的結果是圖書信息,用戶可以選擇查詢該書的更進一步的詳細信息,該包即包含了搜索與展示書籍的相關類。
BrowseBookListener SearrchBookContentsActivity 中的Item按鍵監聽器
SearchBookContentsActivity 聯網”搜索圖書”頁面
SearchBookContentsAdapter Adapter適配器
SearchBookContentsListItem 顯示圖書搜索結果的頁碼和摘要的列表項
SearchBookContentsResult 圖書搜索結果數據bean類
com.google.zxing.client.android.camera 包
- AutoFocusManager implements Camera.AutoFocusCallback 自動對焦
*在CameraManager中被使用*
AutoFocusManager implements Camera.AutoFocusCallback 自動對焦
使用:(在Camera中被使用)
OpenCamera theCamera = camera;
AutoFocusManager autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
1. autoFocusManager.start();
2. autoFocusManager.stop();
- CameraConfigurationManager 設置相機的參數信息類
主要方法:
1. initFromCameraParameters(OpenCamera camera) 計算了屏幕分辨率和當前最適合的相機像素
2. setDesiredCameraParameters(OpenCamera camera, boolean safeMode) 讀取配置設置相機的對焦模式、閃光燈模式等等
3. getPreviewSizeOnScreen()
4. getCameraResolution()
5. getScreenResolution()
6. getCWNeededRotation()
7. getTorchState(Camera camera)
8. setTorch(Camera camera, boolean newSetting)
*第二個方法setDesiredCameraParameters(...)擴展*
1. 可以在這個方法里加 CameraConfigurationUtils.setZoom(parameters, 2.0); 直接固定焦距
2. 可以在setDesiredCameraParameters(Camera camera, boolean safeMode) 方法最後加上:
camera.setDisplayOrientation(90); 設置相機預覽爲豎屏
3. 修改爲豎屏後,由於像素點沒有對調會造成扭曲變形,在 initFromCameraParameters(Camera camera) 方法中:
在Log.d(TAG, "Screen resolution: " + screenResolution);後加上如下的代碼:
/** 因爲換成了豎屏顯示,所以不替換屏幕寬高得出的預覽圖是變形的 */
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
// preview size is always something like 480*320, other 320*480
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
最後,將screenResolution替換爲screenResolutionForCamera:
cameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);
- CameraConfigurationUtils 主要爲CameraConfigurationManager服務的工具類
1.findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) 獲取最佳的相機預覽分辨率
- CameraManager 攝像頭管理類(打開,關閉)
camera/camera.open包的核心類:
- 閃光燈開關,CameraManager.setTorch(true),方法父類是CameraConfigurationManager ,閃光燈開啓同時啓動自動對焦
- 打開攝像頭驅動 CameraManager.openDriver(SurfaceHolder)
- 設置掃碼框顯示位置 getFramingRectInPreview()
- 設置掃碼框矩形的大小(根據屏幕分辨率) getFramingRect()
- 設置掃碼框矩形的大小(自定義 setManualFramingRect(int width, int height))
FrontLightMode 閃光燈枚舉(開,關,自動)
PreviewCallback 當預覽界面出來的時候PreviewCallback.onPreviewFrame()向DecodeHandler 發送一個decode消息,DecodeHandler收到後執行decode方法解碼
com.google.zxing.client.android.camera.open 包
CameraFacing 打開前置或後置攝像頭 枚舉(BACK,FRONT)
OpenCamera bean類(獲取攝像頭部分參數index,camera,facing,orientation )
OpenCameraInterface 打開攝像頭的接口類
這個類被CameraManager 的 OpenDirver() 調用:
OpenCamera theCamera = OpenCameraInterface.open(OpenCameraInterface.NO_REQUESTED_CAMERA);
com.google.zxing.client.android.clipboard 包
- ClipboardInterface 用於調用Android系統自帶的ClipboardManager
com.google.zxing.client.android.encode
編碼功能的各個組件集合。核心類爲QRCodeEncoder,最終實施編碼的是MultiFormatWriter類
ContactEncoder 根據聯繫人信息實現編碼方案,如名片或mecard
EncodeActivity 生成二維碼,全屏顯示的類
Formatter 封裝了一些簡單的格式化邏輯,協助重構{ @link ContactEncoder }。
MECARDContactEncoder 根據MECARD格式編碼的聯繫人信息。
QRCodeEncoder 這個類負責在條形碼編碼時,解碼用戶的請求和提取所有數據
重要方法:
encodeASBitmap() 生成二維碼
VCardContactEncoder 根據名片格式編碼的聯繫信息。
VCardFieldFormatter 名片範圍格式化邏輯
VCardTelDisplayFormatter 名片電話展示格式化邏輯
com.google.zxing.client.android.history 包
DBHelper 創建數據庫,更新數據庫
HistoryActivity “歷史記錄” 頁面,以及邏輯實現
HistoryItem 單條”歷史記錄” 要顯示的內容 bean類
HistoryItemAdapter 歷史記錄 顯示數據用到的適配器
HistoryManager “歷史記錄” 數據庫數據操作 (history包核心類)
- 添加”歷史記錄”
- 保存”歷史記錄”到本地
- 刪除所有”歷史記錄” 方法
- 刪除某一條”歷史記錄” 方法
- CaptureActivity 初始化 HistoryManager 時要刪除的 history ID ,trimHistory()方法
- 查詢 某一條 “歷史記錄”
- 查詢 所有 “歷史記錄 “
com.google.zxing.client.android.result 包
條碼掃描的結果被分爲不同的類型,所有的類型都定義在com.google.zxing.client.result.ParsedResultType中,對於不同的類型都有對應的處理方法:xxxResultHandler,所有的ResultHandler都包含在此包中。不同的xxxResultHandler還提供了掃描結果頁面要展示幾個button,每個button的文本以及需要綁定的事件等等。
AddressBookResultHandler 處理地址簿條目
CalendarResultHandler 處理日曆條目 QR碼的編碼
EmailAddressResultHandler 處理電子郵件地址
GeoResultHandler 處理地理座標(地理編碼:url)
ProductResultHandler 處理不是書的產品
ResultButtonListener 處理條形碼解碼的結果在Android平臺的背景下,通過intent打開GMail等其他Activity,地圖等
ResultHandler 針對android的條形碼的基類處理程序。這允許應用程序使用多態的方式
建議適當的行動爲每個數據類型。
這個類還包含一些實用方法採取共同行動就像打開一個URL。
他們可以很容易地進入一個輔助對象,但它不能是靜態的,因爲Activity實例需要啓動一個意圖。
- ResultHandleFactory (Result包的核心類)
基於條碼內容的類型,生產針對android的處理程序解析掃描二維碼結果,返回對應類型的xxxHandler
這個類的makeResultHandler會調用parseResult方法,parseResult會
調用core類的核心方法,parseResult這個方法是用來解析掃描二維碼得到的結果是屬於那 種類型的數據,調用後返回ParsedResult類,
makeResultHandler方法就用到了getType()來判斷掃描的結果是那一種類型的數據, 類型數據解析完成之後又回到CaptureActivity的handleDecode方法完成對數據的處理。調用:
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); ZXing在CaptureActivity的handleDecode(..)
SMSResultHandle 處理短信地址,提供一個選擇的組合一個新的SMS或MMS消息。
TelResultHandler 提供了電話號碼的相關行爲。
TextResultHandler 這個類處理TextParsedResult以及未知格式。這是回退處理程序。
URIResultHandler 提供了URLS的相關行爲
WifiResultHandler 處理wifi訪問信息
com.google.zxing.client.android.result.supplement 包
對已經掃描並解碼的結果做額外處理的工具集
BookResultInfoRetriever 網頁搜索圖書
ProductResultInfoRetriever 從谷歌產品搜索檢索產品信息
TitleRetriever 檢索一個web頁面的標題作爲補充信息。
URIResultInfoRetriever 網頁跳轉,重定向用的
SupplementalInfoRetriever 這個包中爲其他類的父類
com.google.zxing.client.android.share 包
分享二維碼功能,亦是編碼功能的入口所在
AppInfo 獲取安裝在設備上app相關信息的bean類
AppPickerActivity 獲取安裝在設備上app相關信息的類
BookmarkAdapter 獲取瀏覽器書籤的適配器
BookmarkPickerActivity 獲取瀏覽器書籤 方法類
LoadPackagesAsyncTask: 異步加載在設備上安裝包的列表
ShareActivity 分享功能 界面類
com.google.zxing.client.android.wifi 包
是WifiResultHandler的輔助類集合。如果掃描到的二維碼是對wifi信息的編碼,那麼最終掃描結果頁會展示一個“連接到網絡”的按鈕,點擊此按鈕就會自動嘗試連接。該包中所包含的類則是鏈接網絡所需的工具類。
NetworkType wifi網絡類型類型枚舉(WEP,WPA,NO_PASSWORD)
WifiConfigManager
幾個方法:
1. changeNetworkCommon 用來處理沒有密碼的 wifi連接
2. changeNetworkWEP 用來處理WEP的 wifi連接
3. changeNetworkWPA 用來處理WPA的 wifi連接
4. theWifiResult.getNetworkEncryption(); 得到wifi的類型
判斷wifi連接狀態,解析得到相應的wifi類型,然後連接
相關類:
1.WifiParsedResult 解析wifi類型的掃描結果
2.WifiResultHandler 用來存儲解析後的結果
調用:
WifiParsedResult wifiResult = (WifiParsedResult) getResult();
WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
...
new WifiConfigManager(wifiManager).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, wifiResult);
掃碼流程:
配置Camera並啓動Camera
構建preview與掃描窗口
- 掃描窗口是在CaptureActivityHandler.restartPreviewAndDecode中,通過調用activity.drawViewfinder()來實現的。
- 這裏有個畫掃描窗口的類叫ViewfinderView,該類也是想要改變掃描窗口風格所必須重構的一個類
捕捉畫面並解碼
- Camera.PreviewCallback監聽preView界面是否已經顯示
- PreviewCallback.onPreviewFrame做的事便是當preview界面展示出來的時候向DecodeHandler發送一個decode消息
- DecodeHandler收到該消息後會執行decode方法來解碼。
- Camera.setOneShotPreviewCallback() 檢測並觸發捕獲畫面動作的,該函數被調用後,如果預覽界面已經打開,就會將包含當前preview frame的byte數組傳給回調函數,此時再向DecodeHandler發送decode消息。
將解碼結果交給不同ResultHandler去處理
- DecodeHandler.decode完成解碼後會向CaptureActivityHandler發消息。如果編碼成功則調用CaptureActivity.handleDecode方法對掃描到的結果進行分類處理
- 獲取ResultHandle,
// 解析rawResult,根據不同類型result生成對應的ResultHandler
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
- 調用handleDecodeInternally和handleDecodeExternally對ResultHandler進行處理
總結
這篇文章僅僅是簡閱,可能存在許多不足地方,也研究的不夠深入(如.ZXingTestActivity 一邊測試,一邊研究沒做0.0 …),如果有錯誤的地方歡迎評論指出,一起共同進步…!
精簡版的ZXing網上有很多,這裏就不提供了,後續有時間自己再封裝一個適合自己項目吧…0.0