編輯:關於android開發
先看效果

掃描內容是下面這張,二維碼是用zxing庫生成的

由於改了好幾個類,還是去年的事都忘得差不多了,所以只能上這個類的代碼了,主要就是改了這個CaptureActivity.java
1 package com.zxing.activity;
2
3 import java.io.IOException;
4 import java.util.Vector;
5
6 import android.app.Activity;
7 import android.content.Intent;
8 import android.content.res.AssetFileDescriptor;
9 import android.graphics.Bitmap;
10 import android.media.AudioManager;
11 import android.media.MediaPlayer;
12 import android.media.MediaPlayer.OnCompletionListener;
13 import android.os.Handler;
14 import android.os.Vibrator;
15 import android.view.SurfaceHolder;
16 import android.view.SurfaceHolder.Callback;
17 import android.view.SurfaceView;
18 import android.widget.Toast;
19
20 import com.ericssonlabs.R;
21 import com.google.zxing.BarcodeFormat;
22 import com.google.zxing.Result;
23 import com.zxing.camera.CameraManager;
24 import com.zxing.decoding.CaptureActivityHandler;
25 import com.zxing.decoding.CaptureActivityHandler.DecodeCallback;
26 import com.zxing.decoding.InactivityTimer;
27 import com.zxing.view.ViewfinderView;
28 /**
29 * Initial the camera
30 * @author Ryan.Tang
31 * @modifier Lemon
32 * @use extends CaptureActivity並且在setContentView方法後調用init方法
33 */
34 public abstract class CaptureActivity extends Activity implements Callback, DecodeCallback {
35 // private static final String TAG = "CaptureActivity";
36
37 protected Activity context;
38 protected SurfaceView surfaceView;
39 protected ViewfinderView viewfinderView;
40 /**初始化,必須在setContentView之後
41 * @param context
42 * @param viewfinderView
43 */
44 protected void init(Activity context, SurfaceView surfaceView, ViewfinderView viewfinderView) {
45 this.context = context;
46 this.surfaceView = surfaceView;
47 this.viewfinderView = viewfinderView;
48
49 CameraManager.init(getApplication());
50
51 hasSurface = false;
52 inactivityTimer = new InactivityTimer(this);
53 }
54
55
56 private CaptureActivityHandler handler;
57 private boolean hasSurface;
58 private Vector<BarcodeFormat> decodeFormats;
59 private String characterSet;
60 private InactivityTimer inactivityTimer;
61 private MediaPlayer mediaPlayer;
62 private boolean playBeep;
63 private static final float BEEP_VOLUME = 0.10f;
64 private boolean vibrate;
65
66
67 @Override
68 protected void onResume() {
69 super.onResume();
70 SurfaceHolder surfaceHolder = surfaceView.getHolder();
71 if (hasSurface) {
72 initCamera(surfaceHolder);
73 } else {
74 surfaceHolder.addCallback(this);
75 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
76 }
77 decodeFormats = null;
78 characterSet = null;
79
80 playBeep = true;
81 AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
82 if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
83 playBeep = false;
84 }
85 initBeepSound();
86 vibrate = true;
87 }
88
89 @Override
90 protected void onPause() {
91 super.onPause();
92 if (handler != null) {
93 handler.quitSynchronously();
94 handler = null;
95 }
96 CameraManager.get().closeDriver();
97 }
98
99 @Override
100 protected void onDestroy() {
101 inactivityTimer.shutdown();
102 super.onDestroy();
103 }
104
105
106 public static final String RESULT_QRCODE_STRING = "RESULT_QRCODE_STRING";
107 /**
108 * Handler scan result
109 * @param result
110 * @param barcode
111 */
112 public void handleDecode(Result result, Bitmap barcode) {
113 inactivityTimer.onActivity();
114 playBeepSoundAndVibrate();
115 String resultString = result.getText();
116 //FIXME
117 if (resultString.equals("")) {
118 Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
119 }
120
121 setResult(RESULT_OK, new Intent().putExtra(RESULT_QRCODE_STRING, resultString));
122 finish();
123 }
124
125 private void initCamera(SurfaceHolder surfaceHolder) {
126 try {
127 CameraManager.get().openDriver(surfaceHolder);
128 } catch (IOException ioe) {
129 return;
130 } catch (RuntimeException e) {
131 return;
132 }
133 if (handler == null) {
134 handler = new CaptureActivityHandler(this, decodeFormats,
135 characterSet, viewfinderView, this);
136 }
137 }
138
139 @Override
140 public void drawViewfinder() {
141 viewfinderView.drawViewfinder();
142 }
143
144
145 @Override
146 public void surfaceChanged(SurfaceHolder holder, int format, int width,
147 int height) {
148
149 }
150
151 @Override
152 public void surfaceCreated(SurfaceHolder holder) {
153 if (!hasSurface) {
154 hasSurface = true;
155 initCamera(holder);
156 }
157
158 }
159
160 @Override
161 public void surfaceDestroyed(SurfaceHolder holder) {
162 hasSurface = false;
163
164 }
165
166
167 public Handler getHandler() {
168 return handler;
169 }
170
171
172 private void initBeepSound() {
173 if (playBeep && mediaPlayer == null) {
174 // The volume on STREAM_SYSTEM is not adjustable, and users found it
175 // too loud,
176 // so we now play on the music stream.
177 setVolumeControlStream(AudioManager.STREAM_MUSIC);
178 mediaPlayer = new MediaPlayer();
179 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
180 mediaPlayer.setOnCompletionListener(beepListener);
181
182 AssetFileDescriptor file = getResources().openRawResourceFd(
183 R.raw.beep);
184 try {
185 mediaPlayer.setDataSource(file.getFileDescriptor(),
186 file.getStartOffset(), file.getLength());
187 file.close();
188 mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
189 mediaPlayer.prepare();
190 } catch (IOException e) {
191 mediaPlayer = null;
192 }
193 }
194 }
195
196 private static final long VIBRATE_DURATION = 200L;
197
198 private void playBeepSoundAndVibrate() {
199 if (playBeep && mediaPlayer != null) {
200 mediaPlayer.start();
201 }
202 if (vibrate) {
203 Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
204 vibrator.vibrate(VIBRATE_DURATION);
205 }
206 }
207
208 /**
209 * When the beep has finished playing, rewind to queue up another one.
210 */
211 private final OnCompletionListener beepListener = new OnCompletionListener() {
212 public void onCompletion(MediaPlayer mediaPlayer) {
213 mediaPlayer.seekTo(0);
214 }
215 };
216
217 }
使用方法: 新建一個Activity繼承CaptureActivity並且在setContentView方法後調用init方法即可。
示例:
CameraScanActivity.java
1 package zuo.biao.activity;
2
3 import zuo.biao.R;
4 import zuo.biao.library.interfaces.OnBottomDragListener;
5 import zuo.biao.util.ActivityUtil;
6 import android.content.Context;
7 import android.content.Intent;
8 import android.os.Bundle;
9 import android.view.SurfaceHolder.Callback;
10 import android.view.SurfaceView;
11 import android.view.View;
12 import android.view.View.OnClickListener;
13
14 import com.zxing.activity.CaptureActivity;
15 import com.zxing.camera.CameraManager;
16 import com.zxing.view.ViewfinderView;
17
18 /**掃描二維碼Activity
19 * @author Lemon
20 * @use 參考zuo.biao.library.ModelActivity
21 */
22 public class CameraScanActivity extends CaptureActivity implements Callback, OnClickListener, OnBottomDragListener {
23 public static final String TAG = "CameraScanActivity";
24
25 //啟動方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
26
27 /**啟動這個Activity的Intent
28 * @param context
29 * @param title
30 * @return
31 */
32 public static Intent createIntent(Context context) {
33 return new Intent(context, CameraScanActivity.class);
34 }
35
36 //啟動方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
37
38
39
40 @Override
41 protected void onCreate(Bundle savedInstanceState) {
42 super.onCreate(savedInstanceState);
43 setContentView(R.layout.camera_scan_activity);
44 init(this, (SurfaceView) findViewById(R.id.svCameraScan), (ViewfinderView) findViewById(R.id.vfvCameraScan));
45
46 //功能歸類分區方法,必須調用<<<<<<<<<<
47 initView();
48 initData();
49 initListener();
50 //功能歸類分區方法,必須調用>>>>>>>>>>
51
52 }
53
54
55 //UI顯示區(操作UI,但不存在數據獲取或處理代碼,也不存在事件監聽代碼)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
56
57 public void initView() {//必須調用
58
59 }
60
61
62
63 //UI顯示區(操作UI,但不存在數據獲取或處理代碼,也不存在事件監聽代碼)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
64
65
66
67
68
69
70
71
72
73
74 //data數據區(存在數據獲取或處理代碼,但不存在事件監聽代碼)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
75
76 public void initData() {//必須調用
77
78 }
79
80
81 //data數據區(存在數據獲取或處理代碼,但不存在事件監聽代碼)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
82
83
84
85
86
87
88
89
90 //listener事件監聽區(只要存在事件監聽代碼就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
91
92 public void initListener() {//必須調用
93
94 findViewById(R.id.tvCameraScanReturn).setOnClickListener(this);
95 findViewById(R.id.ivCameraScanReturn).setOnClickListener(this);
96 findViewById(R.id.ivCameraScanLight).setOnClickListener(this);
97 findViewById(R.id.ivCameraScanMyQRCode).setOnClickListener(this);
98 }
99
100 //系統自帶監聽方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
101
102 @Override
103 public void onDragBottom(boolean rightToLeft) {
104 if (rightToLeft) {
105
106 return;
107 }
108
109 finish();
110 }
111
112 @Override
113 public void onClick(View v) {
114 switch (v.getId()) {
115 case R.id.tvCameraScanReturn:
116 case R.id.ivCameraScanReturn:
117 onDragBottom(false);
118 break;
119 case R.id.ivCameraScanLight:
120 switchLight(! isOpen);
121 break;
122 case R.id.ivCameraScanMyQRCode:
123 //
124 break;
125 default:
126 break;
127 }
128 }
129
130
131 private boolean isOpen = false;
132 /**打開或關閉閃關燈
133 * @param open
134 */
135 private void switchLight(boolean open) {
136 if (open == isOpen) {
137 return;
138 }
139 isOpen = CameraManager.get().switchLight(open);
140 }
141
142
143 //類相關監聽<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
144
145
146 //類相關監聽>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
147
148 //系統自帶監聽方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
149
150
151 //listener事件監聽區(只要存在事件監聽代碼就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
152
153
154
155
156
157
158
159
160 //內部類,盡量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
161
162
163
164 //內部類,盡量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
165
166 }
CameraScanActivity布局文件camera_scan_activity.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 > 4 5 <SurfaceView 6 android:id="@+id/svCameraScan" 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:layout_gravity="center" /> 10 11 <!-- 必須在最底層,且不能指定寬高,否則掃描讀取很難實現 --> 12 <com.zxing.view.ViewfinderView 13 android:id="@+id/vfvCameraScan" 14 android:layout_width="match_parent" 15 android:layout_height="match_parent" /> 16 17 <LinearLayout 18 19 android:baselineAligned="false" > 20 21 <RelativeLayout 22 23 android:background="@color/white_alpha" > 24 25 <TextView 26 android:id="@+id/tvCameraScanReturn" 27 28 android:text=" " /> 29 30 <TextView 31 32 android:layout_centerHorizontal="true" 33 android:text="掃一掃" /> 34 </RelativeLayout> 35 36 <LinearLayout 37 38 android:layout_gravity="center_horizontal" 39 android:layout_weight="1" > 40 41 <TextView 42 43 android:layout_margin="30dp" 44 android:text="@string/camera_scan_remind" /> 45 </LinearLayout> 46 47 <LinearLayout 48 49 android:layout_gravity="bottom" 50 android:background="@color/white_alpha" 51 android:gravity="center" > 52 53 <LinearLayout 54 55 android:layout_margin="12dp" 56 android:paddingBottom="4dp" 57 android:paddingLeft="12dp" 58 android:paddingRight="12dp" 59 android:paddingTop="4dp" > 60 61 <ImageView 62 android:id="@+id/ivCameraScanReturn" 63 64 android:background="@drawable/cilcle_gray_to_white" 65 android:padding="12dp" 66 android:src="@drawable/back_black_light" /> 67 68 <TextView 69 70 android:layout_marginTop="4dp" 71 android:text="返回" /> 72 </LinearLayout> 73 74 <LinearLayout 75 76 android:layout_margin="12dp" 77 android:paddingBottom="4dp" 78 android:paddingLeft="12dp" 79 android:paddingRight="12dp" 80 android:paddingTop="4dp" > 81 82 <ImageView 83 android:id="@+id/ivCameraScanLight" 84 85 android:background="@drawable/cilcle_gray_to_white" 86 android:padding="12dp" 87 android:src="@drawable/flash_light" /> 88 89 <TextView 90 91 android:layout_marginTop="4dp" 92 android:text="開燈/關燈" /> 93 </LinearLayout> 94 95 <LinearLayout 96 97 android:layout_margin="12dp" 98 android:paddingBottom="4dp" 99 android:paddingLeft="12dp" 100 android:paddingRight="12dp" 101 android:paddingTop="4dp" > 102 103 <ImageView 104 android:id="@+id/ivCameraScanMyQRCode" 105 106 android:background="@drawable/cilcle_gray_to_white" 107 android:padding="12dp" 108 android:src="@drawable/qrcode" /> 109 110 <TextView 111 112 android:layout_marginTop="4dp" 113 android:text="我的名片" /> 114 </LinearLayout> 115 </LinearLayout> 116 </LinearLayout> 117 118 </FrameLayout>
布局文件因為使用了ZBLibrary中的一些style,color等,只有這個layout的話會出現一些錯誤。自己新建一個layout文件並把ViewfinderView放到最外層布局文件內就行了。當然下載好下面附上的源碼就沒這問題了。
對了,記得在AndroidManifest.xml中加上這些權限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
附源碼(含使用方法)

GitHub源碼 https://github.com/TommyLemon/Android-ZBLibrary
開源中國源碼 http://git.oschina.net/Lemon19950301/Android-ZBLibrary
Android WindowManager實現懸浮窗效果 (一)——與當前Activity綁定,windowmanager懸浮窗
Android WindowManager實現懸浮窗效果 (一)——與當前Activity綁定,windowmanager懸浮窗 最近有學生做畢業設計,想使用懸浮窗這種
Android提權漏洞CVE-2014-7920&CVE-2014-7921分析
Android提權漏洞CVE-2014-7920&CVE-2014-7921分析 這是Android mediaserver的提權漏洞,利用CVE-2014-79
Android--Activity生命周期
Android--Activity生命周期 熟悉javaEE的朋友們都了解servlet技術,我們想要實現一個自己的servlet,需要繼承相應的基類,重寫它的方法,這些
AndroidStudio支持新的NDK的操作使用,androidstudiondk
AndroidStudio支持新的NDK的操作使用,androidstudiondk在2015的Google I / O大會,5月底,谷歌宣布了一項新的支持由Androi
Android WindowManager實現懸浮窗效果 (一)——與當前Activity綁定,windowmanager懸浮窗
Android WindowManager實現懸浮窗效果 (一)——與當