一、效果图:


———————————————————————
有需求者请加qq:136137465,非诚勿扰
(java 架构师全套教程,共760G, 让你从零到架构师,每月轻松拿3万)
01.高级架构师四十二个阶段高
02.Java高级系统培训架构课程148课时
03.Java高级互联网架构师课程
04.Java互联网架构Netty、Nio、Mina等-视频教程
05.Java高级架构设计2016整理-视频教程
06.架构师基础、高级片
07.Java架构师必修linux运维系列课程
08.Java高级系统培训架构课程116课时
(送:hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门)
——————————————————————–

二、框架搭建

1、首先,下载最新zxing开源项目。 下载地址:http://code.google.com/p/zxing/
或 链接:http://pan.baidu.com/s/1c2JRUfQ 密码:hqcg

2、分析项目结构,明确扫描框架需求。在zxing中,有很多其他的功能,项目结构比较复杂;针对二维码QRCode扫描,我们需要几个包:
(1)com.google.zxing.client.android.Camera 基于Camera调用以及参数配置,核心包
(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解码格式、解码线程、解码结果处理的解码类
(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框视图定义的View类
(4)CaptureActivity、CaptureActivityHandler 基于扫描Activity以及扫描结果处理的Capture类
(5)InactivityTimer、BeepManager、FinishListener 基于休眠、声音、退出的辅助管理类
(6)Intents、IntentSource、PrefrencesActivity 基于常量存储的常量类

3、新建工程,添加如下权限permission:

    <uses-permission android:name="android.permission.CAMERA"/>    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.VIBRATE" />    <uses-permission android:name="android.permission.FLASHLIGHT" />

4、 添加core.jar文件,并BuildPath;将上述类或包加入工程后,会报一系列错误,原因有几点:
(1)资源文件缺乏,将zxing下需要的资源文件copy到新工程下
(2)版本兼容问题,zxing下很多技术都是使用4.0版本及以上,集成到低版本之后,须做相应改动,详情参照项目源码
(3)包结构引用问题,需要重新导入包引用

5、最后框架

三、具体实现

1、创建MainActivity用于跳转到扫描页面

/** * 二维码扫描 * @Project    App_ZXing * @Package    com.android.scan * @author     chenlin * @version    1.0 * @Date       2014年3月6日 */public class MainActivity extends Activity {    private Button mBtnScan;    private Button mBtnBack;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mBtnBack = (Button) findViewById(R.id.btn_back);        mBtnBack.setVisibility(View.GONE);        mBtnScan = (Button) findViewById(R.id.btn_scan);        mBtnScan.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(MainActivity.this, ScanActivity.class));            }        });    }}

布局文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <Button        android:id="@+id/btn_scan"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:textColor="@color/white"        android:padding="20dp"        android:background="@drawable/btn_scan_result"        android:text="扫一扫" />    <include            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            layout="@layout/activity_scan_title" />RelativeLayout>

二、扫描页面

/** * 条形码扫描 *  * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 */public class ScanActivity extends Activity implements Callback {    private static final float BEEP_VOLUME = 0.10f;    protected static final String RESULT_TEXT = "result";    protected static final String RESULT_BITMAP = "bitmap";    /** 扫描界面 */    private SurfaceView mSurfaceView;    /** 自定义的View,就是我们看见的拍摄时中间的框框了 */    private ViewfinderView mFindView;    /** 解码处理类,负责调用另外的线程进行解码。 */    private CaptureActivityHandler mHandler;    /** 判断是否创建了SurfaceView */    private boolean hasSurface;    /** decodeFormats 条形码,二维码等的集合 */    private Vector mDecodeFormats;    /** 字符编码 */    private String characterSet;    /** 定时器 */    private InactivityTimer inactivityTimer;    /** 媒体播放器 */    private MediaPlayer mediaPlayer;    /** 是否播放声音 */    private boolean playBeep;    /** 是否震动 */    private boolean vibrate;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_scan);        init();    }    /**     * 初始化     */    private void init() {        mSurfaceView = (SurfaceView) findViewById(R.id.preview_view);        mFindView = (ViewfinderView) findViewById(R.id.viewfinder_view);        CameraManager.init(getApplication());        hasSurface = false;        inactivityTimer = new InactivityTimer(this);    }    /**     * 暂停后恢复时处理内容     */    @SuppressWarnings("all")    @Override    protected void onResume() {        super.onResume();        // 先重新获得holder        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();        if (hasSurface) {            initCamera(surfaceHolder);        } else {            surfaceHolder.addCallback(this);            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        }        mDecodeFormats = null;        characterSet = null;        playBeep = true;        AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);        // 如果当前是铃音模式,则继续准备下面的 蜂鸣提示音操作,如果是静音或者震动模式。就不要继续了。因为用户选择了无声的模式,我们就也不要出声了。        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {            playBeep = false;        }        // 初始化播放声音        initBeepSound();        //播放        vibrate = true;    }    @Override    protected void onPause() {        super.onPause();        if (mHandler != null) {            mHandler.quitSynchronously();            mHandler = null;        }        // 关闭摄像头信息        CameraManager.get().closeDriver();    }    @Override    protected void onDestroy() {        // 关闭定时器        inactivityTimer.shutdown();        super.onDestroy();    }    /**     * 处理扫描结果     *     * @param result     * @param barcode     */    public void handleDecode(Result result, Bitmap barcode) {        // 添加定时器        inactivityTimer.onActivity();        // 响铃和震动        playBeepSoundAndVibrate();        String resultString = result.getText();        if (TextUtils.isEmpty(resultString)) {            ToastUtil.show(this, "扫描失败");            ScanActivity.this.finish();        } else {            //扫描完成后传递结果            Intent resultIntent = new Intent();            resultIntent.setClass(ScanActivity.this, ScanResultActivity.class);            resultIntent.putExtra(RESULT_TEXT, resultString);            ByteArrayOutputStream baos = new ByteArrayOutputStream();            barcode.compress(Bitmap.CompressFormat.PNG, 100, baos);            byte[] bitmapByte = baos.toByteArray();            resultIntent.putExtra(RESULT_BITMAP, bitmapByte);            startActivity(resultIntent);            overridePendingTransition(R.anim.activity_in_from_rigth, R.anim.activity_out_to_scale);            ScanActivity.this.finish();        }    }    private void initCamera(SurfaceHolder surfaceHolder) {        try {            CameraManager.get().openDriver(surfaceHolder);        } catch (IOException ioe) {            return;        } catch (RuntimeException e) {            return;        }        if (mHandler == null) {            mHandler = new CaptureActivityHandler(this, mDecodeFormats, characterSet);        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    /**     * 在视图创建的时候初始化摄像头     */    @Override    public void surfaceCreated(SurfaceHolder holder) {        if (!hasSurface) {            hasSurface = true;            initCamera(holder);        }    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        hasSurface = false;    }    public ViewfinderView getViewfinderView() {        return mFindView;    }    public Handler getHandler() {        return mHandler;    }    public void drawViewfinder() {        mFindView.drawViewfinder();    }    /**     * 初始化声音资源     */    private void initBeepSound() {        // 如果要播放声音并且没有播放器时        if (playBeep && mediaPlayer == null) {            // 设置声道流格式为音乐            setVolumeControlStream(AudioManager.STREAM_MUSIC);            mediaPlayer = new MediaPlayer();            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);            // 设置声音完成后监听            mediaPlayer.setOnCompletionListener(beepListener);            // 设定数据源,并准备播放            AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep);            try {                mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());                file.close();                mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);// 设置音量                mediaPlayer.prepare();            } catch (IOException e) {                mediaPlayer = null;            }        }    }    private static final long VIBRATE_DURATION = 200L;    /**     * 响铃和震动     */    private void playBeepSoundAndVibrate() {        if (playBeep && mediaPlayer != null) {            mediaPlayer.start();        }        if (vibrate) {            Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);            // 震动一次            vibrator.vibrate(VIBRATE_DURATION);            // 第一个参数,指代一个震动的频率数组。每两个为一组,每组的第一个为等待时间,第二个为震动时间。            // 比如 [2000,500,100,400],会先等待2000毫秒,震动500,再等待100,震动400            // 第二个参数,repest指代从 第几个索引(第一个数组参数) 的位置开始循环震动。            // 会一直保持循环,我们需要用 vibrator.cancel()主动终止            // vibrator.vibrate(new long[]{300,500},0);        }    }    /**     * 注册事件。当播放完毕一次后,重新指向流文件的开头,以准备下次播放。     */    private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() {        public void onCompletion(MediaPlayer mediaPlayer) {            mediaPlayer.seekTo(0);        }    };}

布局文件

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent" >        <SurfaceView            android:id="@+id/preview_view"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:layout_gravity="center" />        <com.android.scan.view.ViewfinderView            android:id="@+id/viewfinder_view"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <include            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            layout="@layout/activity_scan_title" />    RelativeLayout>FrameLayout>

3、结果页面

/** *  * @Project App_ZXing * @Package com.android.scan * @author chenlin * @version 1.0 * @Date 2014年3月6日 * @Note TODO */public class ScanResultActivity extends Activity {    private EditText mEtScan;    private Button mBtnBack;    private Button mBtnCopy;    private ImageView mImageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_scan_result);        initViews();        init();    }    private void init() {        final String result = getIntent().getStringExtra(ScanActivity.RESULT_TEXT);        mEtScan.setText(result);        final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);        mBtnBack.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                ScanResultActivity.this.finish();            }        });        mBtnCopy.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (result!=null) {                    ClipData myClip = ClipData.newPlainText("text", result);                    cm.setPrimaryClip(myClip);                }            }        });        //设置图片信息        byte[] imgByte = getIntent().getByteArrayExtra(ScanActivity.RESULT_BITMAP);        if (imgByte != null) {            Drawable drawable = BitmapUtil.byte2Drawable(imgByte);            if (drawable != null) {                mImageView.setImageDrawable(drawable);            }        }    }    // public void paste(View view){    // ClipData abc = myClipboard.getPrimaryClip();    // ClipData.Item item = abc.getItemAt(0);    // String text = item.getText().toString();    // pasteField.setText(text);    // Toast.makeText(getApplicationContext(), "Text Pasted",    // Toast.LENGTH_SHORT).show();    // }    private void initViews() {        mEtScan = (EditText) findViewById(R.id.et_scan_result);        mBtnBack = (Button) findViewById(R.id.btn_back);        mBtnCopy = (Button) findViewById(R.id.btn_copy);    }}

四、代码下载

链接:http://pan.baidu.com/s/1nvesbxB 密码:tyyw

更多相关文章

  1. Android(安卓)查看SharedPreferences中的数据
  2. Android学习之 使用依赖注入函数库Roboguice
  3. Your content must have a ListView whose id attribute is 'and
  4. Android下的图形渲染配置文件egl.cfg
  5. Android(安卓)自定义EditText, 增加设置右边取消按钮的属性
  6. Android个版本适配之7.0
  7. React Native 运行android程序报SDK文件不存在错误
  8. Android之路之十一(SharedPreferences&SQLite数据库)
  9. android文件系统挂载分析(1)---正常开机挂载

随机推荐

  1. 在Android上实现SSL握手
  2. Android(安卓)studio Error:(32, 13) Fai
  3. Android Studio使用技巧小记
  4. 新浪微博1-新浪微博Android(安卓)SDK下载
  5. 关于Unity中Android设备调用震动接口的实
  6. Android配置ssh服务
  7. NativeActivity原理
  8. 关于android开发中的@Override
  9. android 按键控制飞机
  10. Android 系统启动流程简介