先说说我的测试机器:nexus s。以下的结果都是通过nexus s上测试通过。


这次先说说步骤:下载zxing2.0,里面的core有个core.jar这个有用,将它引用到你的工程下。接着在目录android\src\com\google\zxing\client\android\PlanarYUVLuminanceSource.java,将它复制到你的工程的src文件夹下,记得改了它的包名。准备工作就完成了。然后就上代码:

package com.TestCamera2;import com.google.zxing.BinaryBitmap;   import com.google.zxing.MultiFormatReader;   import com.google.zxing.Result;   import com.TestCamera2.PlanarYUVLuminanceSource;   import com.google.zxing.common.HybridBinarizer;   import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.Timer;import java.util.TimerTask;import android.app.Activity;import android.content.Context;import android.content.pm.ActivityInfo;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.ImageFormat;import android.graphics.PixelFormat;import android.graphics.Rect;import android.graphics.YuvImage;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.hardware.Camera.ShutterCallback;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.Display;import android.view.KeyEvent;import android.view.SurfaceHolder;import android.view.View;import android.view.SurfaceHolder.Callback;import android.view.View.OnClickListener;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;public class TestCamera2Activity extends Activity {    private Camera camera;    private SurfaceView surfaceView;    private boolean preview;    final static int width = 352;       final static int height = 288;       int dstLeft, dstTop, dstWidth, dstHeight;       private Timer mTimer;    private MyTimerTask mTimerTask ;    private Button btn;    private Camera.PreviewCallback previewCallback;       @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                requestWindowFeature(Window.FEATURE_NO_TITLE);        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);        Window window = getWindow();        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);        setContentView(R.layout.main);        surfaceView =  (SurfaceView) findViewById(R.id.preview_view);        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        surfaceView.getHolder().setFixedSize(352, 288); //设定surface的大小,必须要,除非你的surface刚好是你手机preview允许的大小                     surfaceView.getHolder().addCallback(new SurfaceViewCallback());       btn=(Button)findViewById(R.id.button1);       btn.setOnClickListener(new OnClickListener(){public void onClick(View v) {mTimer = new Timer();        mTimerTask = new MyTimerTask();        mTimer.schedule(mTimerTask, 0, 80);}       });       previewCallback = new Camera.PreviewCallback() {         public void onPreviewFrame(byte[] data, Camera arg1) {         if(data!=null){         Log.i("data", "ok");        if (dstLeft == 0) {// 只赋值一次                 dstLeft = surfaceView.getLeft() * width                         / getWindowManager().getDefaultDisplay().getWidth();                 dstTop = surfaceView.getTop() * height                         / getWindowManager().getDefaultDisplay().getHeight();                 dstWidth = (surfaceView.getRight() - surfaceView.getLeft())                         * width                         / getWindowManager().getDefaultDisplay().getWidth();                 dstHeight = (surfaceView.getBottom() - surfaceView.getTop())                         * height                         / getWindowManager().getDefaultDisplay().getHeight();             } //PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height, dstLeft, dstTop, dstWidth, dstHeight,false);             // 取得灰度图             Bitmap bm = source.renderCroppedGreyscaleBitmap();             // 保存灰度图             String picDirStr = Environment.getExternalStorageDirectory()+"/";             File picDir = new File(picDirStr);             if(!picDir.exists()){                 picDir.mkdir();             }             String picName = picDirStr + System.currentTimeMillis() + ".jpg";             File myCaptureFile = new File(picName);             try {                 BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(myCaptureFile));                 bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);                 bos.flush();                 bos.close();                 camera.startPreview();                 Log.i("pic","ok");            } catch (Exception e) {                 e.printStackTrace();            }            //                        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));             MultiFormatReader reader = new MultiFormatReader();             try {                 Result result = reader.decode(bitmap);                 String strResult = "BarcodeFormat:"                        + result.getBarcodeFormat().toString() + "  text:"                        + result.getText();                 Log.i("result",strResult);                Toast.makeText(getApplicationContext(), strResult, Toast.LENGTH_LONG+2000).show();            mTimer.cancel();            } catch (Exception e) {              Log.i("result","faile");            } }         else{             Log.i("data", "null");             }         }                         };    }    private final class SurfaceViewCallback implements SurfaceHolder.Callback {        public void surfaceCreated(SurfaceHolder holder) {        camera = Camera.open();              }            public void surfaceChanged(SurfaceHolder holder, int format, int width,                int height) {        Camera.Parameters parameters = camera.getParameters();        parameters.setPreviewSize(width, height);       parameters.setPreviewFrameRate(5);parameters.setPictureFormat(PixelFormat.JPEG);parameters.set("jpeg-quality", 85);        camera.setParameters(parameters);                           try{                       camera.setPreviewDisplay(holder);            preview = true;            Log.i("camera", "camera open!");            }catch(IOException exception) {                 camera.release();                 camera = null;             }         camera.startPreview();        Log.i("camera","camera preview");        }        public void surfaceDestroyed(SurfaceHolder holder) {        if (camera != null) {          if(preview) {                     camera.stopPreview();                     preview = false;                     Log.i("destroyprevie", "ok!");                 }                        camera.release();                 camera = null;             }            }         }    class MyTimerTask extends TimerTask {           @Override          public void run() {              camera.autoFocus(new Camera.AutoFocusCallback() {public void onAutoFocus(boolean success, Camera camera) {if(success){Log.i("focus","ok!");camera.setOneShotPreviewCallback(previewCallback);}}});               }    }}

接着解说一下这个过程:你按button,手机就开始自动对焦(由Timer不断触发),当对焦成功时,调用函数onPreviewFrame来取得那一帧的图片data然后生成对象PlanarYUVLuminanceSource,由这个对象返回一张灰度图,我将它保存下来以便观察。接下来的工作就是交给解码器完成工作了,若解码成功则直接输出解码结果,然后。如果解码不成功,会不断对焦,不断进行尝试。大家可能觉得这个过程十分简单,但是对于这只菜鸟要用一个星期的时间,花时间搞懂照相机,花时间上网找资料,表示看了很多资料http://www.cnblogs.com/liuan/category/347622.html(我从这个博客学到很多,要感谢一下这个博客的博主),花时间看看zxing,然后慢慢学习。这个过程也学习到很多东西。


最后我说说我这个demo的问题。首先看看我的布局文件

<?xml version="1.0" encoding="utf-8"?>  
这样的布局导致不能知道surfaceview的大小,但是surfaceview比较大,所以必须要设定 surfaceView.getHolder().setFixedSize(352, 288);我还操蛋的发现parameters.setPreviewSize(width, height); 根本不起作用的,所以还是不设定好,直接设定surfaceview。然后我将surfaceview设定成352*288,这个surfaceview就太小了而且所得到的灰度图大概只能surfaceview的一半大,所以解码永远不成功的,于是我去看了类 PlanarYUVLuminanceSource的构造函数,但是不知所云。我猜想,因为源程序是满屏幕只取中间那个很小的view的灰度图,所以我的小surfaceview被活生生的截图了(本来就刚刚好找到条形码),所以解码不成功。更多发现留给大家了。所以我直接将surfaceview放得大大好了。


接下来我的android camera系列就结束了(我留给自己的工作是实现跟源程序一样的界面)。这次让我感慨良多。这个是我第一次写这样的文章,发觉是超级难写。因为你要尽量保证你的准确性还要描述清楚(我知道我的表达能力十分有限),那么就不得不做大量的尝试,查看大量的资料(我花了一个多星期吧,才开始接触android两个星期左右)。


附上demo:android camera(4)



警告:android camera系列的文章是由一个刚接触android不到一个月的菜鸟所写,所以必然存在很多错误,请大家指出




更多相关文章

  1. android.uid.system Android中如何修改系统时间(应用程序获得系
  2. android下如何设置系统时间
  3. 代码控制一段时间只触发一次事件(防止多次点击) Android
  4. Android菜鸟的成长笔记——开发环境的搭建
  5. Android常用控件--TimePickerDialog(时间选择对话框)
  6. Android菜鸟日记5
  7. Android获取系统时间方法的总结
  8. android仿微信朋友网、悬浮窗、时间轴、图表、刻度尺、RecyclerV
  9. 转:Android中如何修改系统时间(应用程序获得系统权限)

随机推荐

  1. 【Android】Android 权限大全
  2. Android API 中文(14) —— ViewStub
  3. Android——Intent 相关
  4. Android 热补丁动态修复框架小结
  5. Android 检查版本更新 Server后台下载
  6. Android的几种数据存储方式
  7. Android(安卓)selector的item里的属性说
  8. Android(安卓)Gallery控件使用方法详解
  9. android课后作业
  10. Android中bitmap图片透明度的处理(以撕美