前几天在群里吹牛逼,说到微信的扫码怎么怎么吊.怎么怎么厉害..
当时一阵不服气.决定自己封装扫码器,后来搜了下,市场上大多数都是zxing和zbar.然后c语言我又不会,只能去封装zxing.
后来工作没事情做,正好抽时间补了一下,把zbar给封装一编,做出一个最简单的扫码器.
微信扫码是真的快,爱奇艺也是,不过我反编译看了下,他们用的满多jni还有都是zxing.
以下是我封装zbar地址,贼简单.具体可以看下demo
https://github.com/ccx1/EZbar
首先我们需要了解一下,zbar编译需要啥.我看了严大的博客.在结合自己的,一步一步实现编译集成
Zbar的官网可以下载已经编译好的so和jar,不过so库版本只有armeabi
、armeabi-v7a
、x86
平台
所以我决定,自己来
先下载一波zbar的源码
https://github.com/ZBar/ZBar
然后需要下载libiconv,下载最新版本就好了,我下载的是最新的1.7版本,反正,蛮好用.
https://ftp.gnu.org/pub/gnu/libiconv/
然后准备工程完成之后呢,先解压libiconv.
然后进入到文件夹中.执行命令行.
注意:这里编译需要linux系统,.我是mac,我编译了半天.一直出错.=-=,这里非常关键,如果没有权限.sudo chmod 777 configure
./configure
然后编译完成之后执行
make
这就编译好了,然后从linux把这个拿下里,我拿下来的时候是通过压缩,然后sz命令拿下来的
这时候libiconv已经编译好了.
然后修改一些参数
打开libiconv
libiconv-1.7 -> libcharset -> config.h
第43行的样子,把最后位的1改成0
原先:
/* Define if you have and nl_langinfo(CODESET). */
#define HAVE_LANGINFO_CODESET 1
改完后:
/* Define if you have and nl_langinfo(CODESET). */
#define HAVE_LANGINFO_CODESET 0
第二步打开
libiconv-1.7 -> libcharset -> lib -> localcharset.c
然后
找到int c; 在get_charset_aliases()方法中.全局搜索也可以
修改成
libiconv暂时告一段落.
在andorid工程的src/main目录下创建一个jni文件夹.然后.把刚刚编译的libiconv,以及下载过来的zbar组件拿过来.
1. 把libiconv拿过来放到jni目录下面
2. zbar/include 这个include整个拿进去.
3. zbarjni.c 放到刚刚创建的jni目录下,这个文件在zbar/java目录下面.
4. 把zbar core库拿过来,也就是zbar/zbar目录放到jni下面
5. 在zbar目录下面的Android.mk、Applicaiton.mk、config.h从zbar\android\jni 拿到项目目录jni下面
目录下就这些文件,都放在jni目录下面.
然后接着开始修改Android.mk.先是修改一波路径
首先介绍一波原版,需要修改libiconv的LOCAL_PATH以及所有跟路径有关的东西
zbar的地方也是修改所有路径,
#
# Android NDK makefile
#
# build - /ndk-build ICONV_SRC=
# clean - /ndk-build clean
#
MY_LOCAL_PATH := $(call my-dir)
# libiconv 这边是编译libiconv
include $(CLEAR_VARS)
LOCAL_PATH := $(ICONV_SRC)
LOCAL_MODULE := libiconv
LOCAL_CFLAGS := \
-Wno-multichar \
-D_ANDROID \
-DLIBDIR="c" \
-DBUILDING_LIBICONV \
-DBUILDING_LIBCHARSET \
-DIN_LIBRARY
LOCAL_SRC_FILES := \
lib/iconv.c \
libcharset/lib/localcharset.c \
lib/relocatable.c
LOCAL_C_INCLUDES := \
$(ICONV_SRC)/include \
$(ICONV_SRC)/libcharset \
$(ICONV_SRC)/libcharset/include
include $(BUILD_SHARED_LIBRARY)
LOCAL_LDLIBS := -llog -lcharset
# libzbarjni 编译zbar
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := zbarjni
LOCAL_SRC_FILES := ../../java/zbarjni.c \
../../zbar/img_scanner.c \
../../zbar/decoder.c \
../../zbar/image.c \
../../zbar/symbol.c \
../../zbar/convert.c \
../../zbar/config.c \
../../zbar/scanner.c \
../../zbar/error.c \
../../zbar/refcnt.c \
../../zbar/video.c \
../../zbar/video/null.c \
../../zbar/decoder/code128.c \
../../zbar/decoder/code39.c \
../../zbar/decoder/code93.c \
../../zbar/decoder/codabar.c \
../../zbar/decoder/databar.c \
../../zbar/decoder/ean.c \
../../zbar/decoder/i25.c \
../../zbar/decoder/qr_finder.c \
../../zbar/qrcode/bch15_5.c \
../../zbar/qrcode/binarize.c \
../../zbar/qrcode/isaac.c \
../../zbar/qrcode/qrdec.c \
../../zbar/qrcode/qrdectxt.c \
../../zbar/qrcode/rs.c \
../../zbar/qrcode/util.c
LOCAL_C_INCLUDES := ../include \
../zbar \
$(ICONV_SRC)/include
LOCAL_SHARED_LIBRARIES := libiconv
include $(BUILD_SHARED_LIBRARY)
改完之后.
#
# Android NDK makefile
#
# build - /ndk-build ICONV_SRC=
# clean - /ndk-build clean
#
MY_LOCAL_PATH := $(call my-dir)
# libiconv
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := libiconv
LOCAL_CFLAGS := \
-Wno-multichar \
-D_ANDROID \
-DLIBDIR="c" \
-DBUILDING_LIBICONV \
-DBUILDING_LIBCHARSET \
-DIN_LIBRARY
LOCAL_SRC_FILES := \
libiconv-1.7/lib/iconv.c \
libiconv-1.7/libcharset/lib/localcharset.c
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/libiconv-1.7/include \
$(LOCAL_PATH)/libiconv-1.7/libcharset \
$(LOCAL_PATH)/libiconv-1.7/libcharset/include
include $(BUILD_SHARED_LIBRARY)
LOCAL_LDLIBS := -llog -lcharset
# -----------------------------------------------------
# libzbarjni
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := zbarjni
LOCAL_SRC_FILES := \
zbarjni.c \
zbar/img_scanner.c \
zbar/decoder.c \
zbar/image.c \
zbar/symbol.c \
zbar/convert.c \
zbar/config.c \
zbar/scanner.c \
zbar/error.c \
zbar/refcnt.c \
zbar/video.c \
zbar/video/null.c \
zbar/decoder/code128.c \
zbar/decoder/code39.c \
zbar/decoder/code93.c \
zbar/decoder/codabar.c \
zbar/decoder/databar.c \
zbar/decoder/ean.c \
zbar/decoder/i25.c \
zbar/decoder/qr_finder.c \
zbar/qrcode/bch15_5.c \
zbar/qrcode/binarize.c \
zbar/qrcode/isaac.c \
zbar/qrcode/qrdec.c \
zbar/qrcode/qrdectxt.c \
zbar/qrcode/rs.c \
zbar/qrcode/util.c
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/zbar \
$(LOCAL_PATH)/libiconv-1.7/include
LOCAL_SHARED_LIBRARIES := libiconv
include $(BUILD_SHARED_LIBRARY)
然后开始修改Applicaiton.mk.
这个里面涉及到了你需要产生哪写.so库.
我直接塞了一个all进去.全部生成
原版:
APP_ABI := armeabi armeabi-v7a x86
修改后
APP_ABI := all
开始编译.
进入到jni目录.
也就是src/main/jni目录下.然后输入
ndk-build
如果没有ndk,以及没有配ndk的环境.会报错.下载完成需要配个环境变量
ndk下载地址
然后输入命令,你的目录下会产生一个obj目录,一个lib目录,lib目录就是我们要找的.
然后拷贝lib目录下的东西,放到libs下面,也就是以下这些,.
然后需要在build.gradle里面配置,这里一定要这么做.
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
然后把zbar/java的net文件夹拷贝出来,放到src/main/java下.
包名都不能改.我尝试改了下,报错了.因为c语言里面设置了包的使用路径.太多了,我就不想改了,如果有兴趣的小伙伴,可以进去改一下
这里必须要这么做,不然会崩
然后把Android目录下的examples拿出来.这就是集成样例.
zbar/Android/examples
直接运行,这里需要给照相机权限.
完成
扫码的核心方法就是,camera的onPreviewFrame回调.
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
int result = scanner.scanImage(barcode);
if (result != 0) {
mCameraManager.stop();
SymbolSet syms = scanner.getResults();
// 扫码结果页
for (Symbol sym : syms) {
System.out.println(sym.getData());
}
}
}
这是我的github地址,jni.zip是我已经编译好的.ndk-build.也可以直接出so文件
https://github.com/ccx1/EZbar
这里的viewfinderview,是我拿我以前的项目,封装zxing的时候写的.
这里zxing我那时候优化了很久,终于达到聚焦扫码快速的时候.
https://github.com/ccx1/EZxing