今天研究了一下,Android中怎么实现二维码的扫描功能,在网上查了一下资料,找到一个简单方便的库ZBar bar code reader。首先要添加ZBar bar库zbar.jar,如图所示
添加权限:
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-feature android:name="android.hardware.camera" />
- <uses-feature android:name="android.hardware.camera.autofocus" />
定义一个类继承SurfaceView来预览二维码,代码:
- /** A basic Camera preview class */
- public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
- private SurfaceHolder mHolder;
- private Camera mCamera;
- private PreviewCallback previewCallback;
- private AutoFocusCallback autoFocusCallback;
- public CameraPreview(Context context, Camera camera,
- PreviewCallback previewCb,
- AutoFocusCallback autoFocusCb) {
- super(context);
- mCamera = camera;
- previewCallback = previewCb;
- autoFocusCallback = autoFocusCb;
- /*
- * Set camera to continuous focus if supported, otherwise use
- * software auto-focus. Only works for API level >=9.
- */
- /*
- Camera.Parameters parameters = camera.getParameters();
- for (String f : parameters.getSupportedFocusModes()) {
- if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
- mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
- autoFocusCallback = null;
- break;
- }
- }
- */
- // Install a SurfaceHolder.Callback so we get notified when the
- // underlying surface is created and destroyed.
- mHolder = getHolder();
- mHolder.addCallback(this);
- // deprecated setting, but required on Android versions prior to 3.0
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- }
- public void surfaceCreated(SurfaceHolder holder) {
- // The Surface has been created, now tell the camera where to draw the preview.
- try {
- mCamera.setPreviewDisplay(holder);
- } catch (IOException e) {
- Log.d("DBG", "Error setting camera preview: " + e.getMessage());
- }
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- // Camera preview released in activity
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- /*
- * If your preview can change or rotate, take care of those events here.
- * Make sure to stop the preview before resizing or reformatting it.
- */
- if (mHolder.getSurface() == null){
- // preview surface does not exist
- return;
- }
- // stop preview before making changes
- try {
- mCamera.stopPreview();
- } catch (Exception e){
- // ignore: tried to stop a non-existent preview
- }
- try {
- // Hard code camera surface rotation 90 degs to match Activity view in portrait
- mCamera.setDisplayOrientation(90);
- mCamera.setPreviewDisplay(mHolder);
- mCamera.setPreviewCallback(previewCallback);
- mCamera.startPreview();
- mCamera.autoFocus(autoFocusCallback);
- } catch (Exception e){
- Log.d("DBG", "Error starting camera preview: " + e.getMessage());
- }
- }
- }
主Activity的代码:
- /* Import ZBar Class files */
- public class CameraTestActivity extends Activity
- {
- private Camera mCamera;
- private CameraPreview mPreview;
- private Handler autoFocusHandler;
- TextView scanText;
- Button scanButton;
- ImageScanner scanner;
- private boolean barcodeScanned = false;
- private boolean previewing = true;
- static {
- System.loadLibrary("iconv");
- }
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- autoFocusHandler = new Handler();
- mCamera = getCameraInstance();
- /* Instance barcode scanner */
- scanner = new ImageScanner();
- scanner.setConfig(0, Config.X_DENSITY, 3);
- scanner.setConfig(0, Config.Y_DENSITY, 3);
- mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
- FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
- preview.addView(mPreview);
- scanText = (TextView)findViewById(R.id.scanText);
- scanButton = (Button)findViewById(R.id.ScanButton);
- scanButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- if (barcodeScanned) {
- barcodeScanned = false;
- scanText.setText("Scanning...");
- mCamera.setPreviewCallback(previewCb);
- mCamera.startPreview();
- previewing = true;
- mCamera.autoFocus(autoFocusCB);
- }
- }
- });
- }
- public void onPause() {
- super.onPause();
- releaseCamera();
- }
- /** A safe way to get an instance of the Camera object. */
- public static Camera getCameraInstance(){
- Camera c = null;
- try {
- c = Camera.open();
- } catch (Exception e){
- }
- return c;
- }
- private void releaseCamera() {
- if (mCamera != null) {
- previewing = false;
- mCamera.setPreviewCallback(null);
- mCamera.release();
- mCamera = null;
- }
- }
- private Runnable doAutoFocus = new Runnable() {
- public void run() {
- if (previewing)
- mCamera.autoFocus(autoFocusCB);
- }
- };
- PreviewCallback previewCb = new PreviewCallback() {
- public void onPreviewFrame(byte[] data, Camera camera) {
- Camera.Parameters parameters = camera.getParameters();
- Size size = parameters.getPreviewSize();
- Image barcode = new Image(size.width, size.height, "Y800");
- barcode.setData(data);
- int result = scanner.scanImage(barcode);
- if (result != 0) {
- previewing = false;
- mCamera.setPreviewCallback(null);
- mCamera.stopPreview();
- SymbolSet syms = scanner.getResults();
- for (Symbol sym : syms) {
- scanText.setText("barcode result " + sym.getData());
- barcodeScanned = true;
- }
- }
- }
- };
- // Mimic continuous auto-focusing
- AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
- public void onAutoFocus(boolean success, Camera camera) {
- autoFocusHandler.postDelayed(doAutoFocus, 1000);
- }
- };
- }
以上就是使用ZBar库来扫描二维码。
详细资料:http://sourceforge.net/p/zbar/news/2012/03/zbar-android-sdk-version-01-released/。