参考文章:http://www.cnblogs.com/keyindex/archive/2011/06/08/2074900.html
在开始前大致介绍一下简化ZXing需要用到各个包 、类的职责。
新建另一个项目将启动的Activity命名为CaptureActivity,并导入核心库。项目新建完成后我们打开 CaptureActivity 的布局文件,我这里为main。把里面的XML修改为:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <SurfaceView android:id="@+id/preview_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerInParent="true"/> <com.Zxing.Demo.view.ViewfinderView android:id="@+id/viewfinder_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/transparent"/> <TextView android:layout_width="wrap_content" android:id="@+id/txtResult" android:layout_height="wrap_content" android:text="@string/hello"/> </FrameLayout>
打开 CaptureActivity 覆盖 onCreate 方法:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化 CameraManager
CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
txtResult = (TextView) findViewById(R.id.txtResult);
hasSurface =false;
inactivityTimer =new InactivityTimer(this);
}
这里调用到的 CameraManager 类是控制摄像头的包里的类。新建一个camera包把:com.google.zxing.client.android.camera 里面的类全部拷入,另外我把PlanarYUVLuminanceSource也拷入到这个包里面。
在修改的过程中,有很多是关于R 资源的问题,在此我们需要将Values 里面的两个xml资源文件拷入项目中:colos.xml 和ids.xml 。 ctrl+b 一下看看error 是不是少了很多。在CameraManager中有些地方需要用到项目的配置,这里需要把配置直接写入代码中:
<uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.FLASHLIGHT"/>当View 和 camera 包里的错误修正完成后,我们继续来看CaptureActivity。
@Override protected void onResume() { super.onResume(); SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); SurfaceHolder surfaceHolder = surfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } decodeFormats =null; characterSet =null; playBeep =true; AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE); if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { playBeep =false; } initBeepSound(); vibrate =true; }initCamera()方法的代码
initCamera private void initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (handler ==null) { handler =new CaptureActivityHandler(this, decodeFormats, characterSet); } }
SurfaceHolder接口实现 @Override publicvoid surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override publicvoid surfaceCreated(SurfaceHolder holder) { if (!hasSurface) { hasSurface =true; initCamera(holder); } } @Override publicvoid surfaceDestroyed(SurfaceHolder holder) { hasSurface =false; }
initCamera () 方法用于初始化摄像头,如果排除了所有的error ,运行项目时就可以看到大致扫描界面了。 surfaceHolder.addCallback(this);表示让CaptureActivity实现其callback接口。
handler = new CaptureActivityHandler(this, decodeFormats,characterSet) 用于进行扫描解码处理。
上面的步骤主要都是用于对摄像头的控制,而解码的真正工作入口是在CaptureActivityHandler 里面的。新建一个Decoding包把以下文件拷入包中:
由于我们的包结构和Zxing 项目的有所不同所以需要注意一下类的可访问性
同样开始ctrl+B 编译一下,然后开始修正错误。
在CaptureActivityHandler 里 把 handleMessage 里的部分方法先注释掉如:“decode_succeeded ”分支,这是解码成功时调用 CaptureActivity 展示解码的结果。
在DecodeThread 类里,修改部分涉及Preference配置的代码:
DecodeThread(CaptureActivity activity, Vector<BarcodeFormat> decodeFormats, String characterSet, ResultPointCallback resultPointCallback) { this.activity = activity; handlerInitLatch =new CountDownLatch(1); hints =new Hashtable<DecodeHintType, Object>(3); //// The prefs can't change while the thread is running, so pick them up once here. // if (decodeFormats == null || decodeFormats.isEmpty()) { // SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); // decodeFormats = new Vector<BarcodeFormat>(); // if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) { // decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); // } // if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) { // decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS); // } // if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) { // decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS); // } // } if (decodeFormats ==null|| decodeFormats.isEmpty()) { decodeFormats =new Vector<BarcodeFormat>(); decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS); decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS); } hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats); if (characterSet !=null) { hints.put(DecodeHintType.CHARACTER_SET, characterSet); } hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback); }
这里是设置 解码的类型,我们现在默认将所有类型都加入。
还记得在 CaptureActivityHandler 的 messagehandler 里注销掉的Case分支吗?现在CaptureActivity 里实现它。
错误类型基本上都是:包结构、PreferencesActivity 的配置 、类可访问性的问题。根据错误提示耐心把错误解决。
publicvoid handleDecode(Result obj, Bitmap barcode) { inactivityTimer.onActivity(); viewfinderView.drawResultBitmap(barcode); playBeepSoundAndVibrate(); txtResult.setText(obj.getBarcodeFormat().toString() +":" + obj.getText()); }ZXing的简化已基本完成,有几位是可以运行成功的?呵呵。
CaputreActivity publicclass CaptureActivity extends Activity implements Callback { private CaptureActivityHandler handler; private ViewfinderView viewfinderView; privateboolean hasSurface; private Vector<BarcodeFormat> decodeFormats; private String characterSet; private TextView txtResult; private InactivityTimer inactivityTimer; private MediaPlayer mediaPlayer; privateboolean playBeep; privatestaticfinalfloat BEEP_VOLUME =0.10f; privateboolean vibrate; /** Called when the activity is first created. */ @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //初始化 CameraManager CameraManager.init(getApplication()); viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); txtResult = (TextView) findViewById(R.id.txtResult); hasSurface =false; inactivityTimer =new InactivityTimer(this); } @Override protectedvoid onResume() { super.onResume(); SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); SurfaceHolder surfaceHolder = surfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } decodeFormats =null; characterSet =null; playBeep =true; AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE); if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { playBeep =false; } initBeepSound(); vibrate =true; } @Override protectedvoid onPause() { super.onPause(); if (handler !=null) { handler.quitSynchronously(); handler =null; } CameraManager.get().closeDriver(); } @Override protectedvoid onDestroy() { inactivityTimer.shutdown(); super.onDestroy(); } privatevoid initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (handler ==null) { handler =new CaptureActivityHandler(this, decodeFormats, characterSet); } } @Override publicvoid surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override publicvoid surfaceCreated(SurfaceHolder holder) { if (!hasSurface) { hasSurface =true; initCamera(holder); } } @Override publicvoid surfaceDestroyed(SurfaceHolder holder) { hasSurface =false; } public ViewfinderView getViewfinderView() { return viewfinderView; } public Handler getHandler() { return handler; } publicvoid drawViewfinder() { viewfinderView.drawViewfinder(); } publicvoid handleDecode(Result obj, Bitmap barcode) { inactivityTimer.onActivity(); viewfinderView.drawResultBitmap(barcode); playBeepSoundAndVibrate(); txtResult.setText(obj.getBarcodeFormat().toString() +":" + obj.getText()); } privatevoid initBeepSound() { if (playBeep && mediaPlayer ==null) { // The volume on STREAM_SYSTEM is not adjustable, and users found it // too loud, // so we now play on the music stream. 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; } } } privatestaticfinallong VIBRATE_DURATION =200L; privatevoid playBeepSoundAndVibrate() { if (playBeep && mediaPlayer !=null) { mediaPlayer.start(); } if (vibrate) { Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator.vibrate(VIBRATE_DURATION); } } /** * When the beep has finished playing, rewind to queue up another one. */ privatefinal OnCompletionListener beepListener =new OnCompletionListener() { publicvoid onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } };
源码下载:http://download.csdn.net/detail/kaka89757/5268842