导读
- 虽然有句话在程序员中说:”别人造好的*,不要重复发明*”,但是只会用别人的东西,对自己个人技术的提升也是不可能的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