CaptureActivity.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. package me.yoqi.qrcode;
  2. import android.Manifest;
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.content.pm.PackageManager;
  6. import android.graphics.Bitmap;
  7. import android.graphics.Canvas;
  8. import android.graphics.Paint;
  9. import android.os.Build;
  10. import android.os.Bundle;
  11. import android.os.Handler;
  12. import android.os.Message;
  13. import android.util.Log;
  14. import android.view.KeyEvent;
  15. import android.view.SurfaceHolder;
  16. import android.view.SurfaceView;
  17. import android.view.View;
  18. import android.view.View.OnClickListener;
  19. import android.view.Window;
  20. import android.view.WindowManager;
  21. import android.widget.ImageView;
  22. import android.widget.Toast;
  23. import com.google.zxing.BarcodeFormat;
  24. import com.google.zxing.Result;
  25. import com.google.zxing.ResultPoint;
  26. import com.google.zxing.client.android.camera.CameraManager;
  27. import com.google.zxing.client.android.decode.BeepManager;
  28. import com.google.zxing.client.android.decode.CaptureActivityHandler;
  29. import com.google.zxing.client.android.decode.InactivityTimer;
  30. import com.google.zxing.client.android.decode.ViewfinderView;
  31. import com.google.zxing.client.android.result.ResultHandler;
  32. import com.google.zxing.client.android.result.ResultHandlerFactory;
  33. import java.io.IOException;
  34. import java.util.Collection;
  35. /**
  36. * 识别二维码 CaptureActivity
  37. *
  38. * @author liuyuqi
  39. *
  40. */
  41. public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {
  42. private static final String TAG = CaptureActivity.class.getSimpleName();
  43. private CameraManager cameraManager;
  44. private CaptureActivityHandler handler;
  45. private Result savedResultToShow;
  46. private ViewfinderView viewfinderView;
  47. private boolean hasSurface;
  48. private Collection<BarcodeFormat> decodeFormats;
  49. private InactivityTimer inactivityTimer;
  50. private String characterSet;
  51. private BeepManager beepManager;
  52. ImageView opreateView;
  53. ViewfinderView getViewfinderView() {
  54. return viewfinderView;
  55. }
  56. public Handler getHandler() {
  57. return handler;
  58. }
  59. public CameraManager getCameraManager() {
  60. return cameraManager;
  61. }
  62. @Override
  63. public void onCreate(Bundle icicle) {
  64. super.onCreate(icicle);
  65. Window window = getWindow();
  66. window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  67. setContentView(R.layout.capture);
  68. hasSurface = false;
  69. inactivityTimer = new InactivityTimer(this);
  70. beepManager = new BeepManager(this);
  71. opreateView = (ImageView) findViewById(R.id.button_openorcloseClick);
  72. opreateView.setOnClickListener(new OnClickListener() {
  73. @Override
  74. public void onClick(View v) {
  75. if (cameraManager != null) {
  76. Config.KEY_FRONT_LIGHT = !Config.KEY_FRONT_LIGHT;
  77. if (Config.KEY_FRONT_LIGHT == true) {
  78. opreateView
  79. .setImageResource(R.drawable.mzw_camera_close);
  80. } else {
  81. opreateView
  82. .setImageResource(R.drawable.mzw_camera_open);
  83. }
  84. cameraManager.getConfigManager().initializeTorch(
  85. cameraManager.getCamera().getParameters(), false);
  86. onPause();
  87. onResume();
  88. }
  89. }
  90. });
  91. }
  92. @Override
  93. protected void onResume() {
  94. super.onResume();
  95. // CameraManager must be initialized here, not in onCreate(). This is
  96. // necessary because we don't
  97. // want to open the camera driver and measure the screen size if we're
  98. // going to show the help on
  99. // first launch. That led to bugs where the scanning rectangle was the
  100. // wrong size and partially
  101. // off screen.
  102. cameraManager = new CameraManager(getApplication());
  103. viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
  104. viewfinderView.setCameraManager(cameraManager);
  105. handler = null;
  106. SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
  107. SurfaceHolder surfaceHolder = surfaceView.getHolder();
  108. if (hasSurface) {
  109. // The activity was paused but not stopped, so the surface still
  110. // exists. Therefore
  111. // surfaceCreated() won't be called, so init the camera here.
  112. initCamera(surfaceHolder);
  113. } else {
  114. // Install the callback and wait for surfaceCreated() to init the
  115. // camera.
  116. surfaceHolder.addCallback(this);
  117. surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  118. }
  119. beepManager.updatePrefs();
  120. inactivityTimer.onResume();
  121. }
  122. @Override
  123. protected void onPause() {
  124. if (handler != null) {
  125. handler.quitSynchronously();
  126. handler = null;
  127. }
  128. inactivityTimer.onPause();
  129. cameraManager.closeDriver();
  130. if (!hasSurface) {
  131. SurfaceView surfaceView = findViewById(R.id.preview_view);
  132. SurfaceHolder surfaceHolder = surfaceView.getHolder();
  133. surfaceHolder.removeCallback(this);
  134. }
  135. super.onPause();
  136. }
  137. @Override
  138. protected void onStop() {
  139. if (handler != null) {
  140. handler.quitSynchronously();
  141. handler = null;
  142. }
  143. cameraManager.closeDriver();
  144. if (!hasSurface) {
  145. SurfaceView surfaceView = findViewById(R.id.preview_view);
  146. SurfaceHolder surfaceHolder = surfaceView.getHolder();
  147. surfaceHolder.removeCallback(this);
  148. }
  149. super.onStop();
  150. }
  151. @Override
  152. protected void onDestroy() {
  153. inactivityTimer.shutdown();
  154. super.onDestroy();
  155. }
  156. @Override
  157. public boolean onKeyDown(int keyCode, KeyEvent event) {
  158. switch (keyCode) {
  159. case KeyEvent.KEYCODE_BACK:
  160. // restartPreviewAfterDelay(0L);
  161. return super.onKeyDown(keyCode, event);
  162. case KeyEvent.KEYCODE_FOCUS:
  163. case KeyEvent.KEYCODE_CAMERA:
  164. // Handle these events so they don't launch the Camera app
  165. return true;
  166. // Use volume up/down to turn on light
  167. case KeyEvent.KEYCODE_VOLUME_DOWN:
  168. cameraManager.setTorch(false);
  169. return true;
  170. case KeyEvent.KEYCODE_VOLUME_UP:
  171. cameraManager.setTorch(true);
  172. return true;
  173. }
  174. return super.onKeyDown(keyCode, event);
  175. }
  176. private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) {
  177. // Bitmap isn't used yet -- will be used soon
  178. if (handler == null) {
  179. savedResultToShow = result;
  180. } else {
  181. if (result != null) {
  182. savedResultToShow = result;
  183. }
  184. if (savedResultToShow != null) {
  185. Message message = Message.obtain(handler,
  186. R.id.decode_succeeded, savedResultToShow);
  187. handler.sendMessage(message);
  188. }
  189. savedResultToShow = null;
  190. }
  191. }
  192. @Override
  193. public void surfaceCreated(SurfaceHolder holder) {
  194. if (holder == null) {
  195. Log.e(TAG,
  196. "*** WARNING *** surfaceCreated() gave us a null surface!");
  197. }
  198. if (!hasSurface) {
  199. hasSurface = true;
  200. initCamera(holder);
  201. }
  202. }
  203. @Override
  204. public void surfaceDestroyed(SurfaceHolder holder) {
  205. hasSurface = false;
  206. }
  207. @Override
  208. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  209. int height) {
  210. }
  211. /**
  212. * A valid barcode has been found, so give an indication of success and show
  213. * the results.
  214. *
  215. * @param rawResult
  216. * The contents of the barcode.
  217. * @param barcode
  218. * A greyscale bitmap of the camera data which was decoded.
  219. */
  220. public void handleDecode(Result rawResult, Bitmap barcode) {
  221. inactivityTimer.onActivity();
  222. ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(
  223. this, rawResult);
  224. boolean fromLiveScan = barcode != null;
  225. if (fromLiveScan) {
  226. // Then not from history, so beep/vibrate and we have an image to
  227. // draw on
  228. beepManager.playBeepSoundAndVibrate();
  229. // drawResultPoints(barcode, rawResult);
  230. viewfinderView.drawResultBitmap(barcode);
  231. }
  232. String text = rawResult.getText();
  233. Intent intent = new Intent(this, ResultActivity.class);
  234. intent.putExtra("text", text);
  235. startActivity(intent);
  236. cameraManager.closeDriver();
  237. }
  238. /**
  239. * Superimpose a line for 1D or dots for 2D to highlight the key features of
  240. * the barcode.
  241. *
  242. * @param barcode
  243. * A bitmap of the captured image.
  244. * @param rawResult
  245. * The decoded results which contains the points to draw.
  246. */
  247. private void drawResultPoints(Bitmap barcode, Result rawResult) {
  248. ResultPoint[] points = rawResult.getResultPoints();
  249. if (points != null && points.length > 0) {
  250. Canvas canvas = new Canvas(barcode);
  251. Paint paint = new Paint();
  252. paint.setColor(getResources().getColor(R.color.result_points));
  253. if (points.length == 2) {
  254. paint.setStrokeWidth(4.0f);
  255. drawLine(canvas, paint, points[0], points[1]);
  256. } else if (points.length == 4
  257. && (rawResult.getBarcodeFormat() == BarcodeFormat.UPC_A || rawResult
  258. .getBarcodeFormat() == BarcodeFormat.EAN_13)) {
  259. // Hacky special case -- draw two lines, for the barcode and
  260. // metadata
  261. drawLine(canvas, paint, points[0], points[1]);
  262. drawLine(canvas, paint, points[2], points[3]);
  263. } else {
  264. paint.setStrokeWidth(10.0f);
  265. for (ResultPoint point : points) {
  266. canvas.drawPoint(point.getX(), point.getY(), paint);
  267. }
  268. }
  269. }
  270. }
  271. private static void drawLine(Canvas canvas, Paint paint, ResultPoint a,
  272. ResultPoint b) {
  273. canvas.drawLine(a.getX(), a.getY(), b.getX(), b.getY(), paint);
  274. }
  275. private void initCamera(SurfaceHolder surfaceHolder) {
  276. // 权限检测
  277. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  278. if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
  279. requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
  280. }
  281. }
  282. if (surfaceHolder == null) {
  283. throw new IllegalStateException("No SurfaceHolder provided");
  284. }
  285. if (cameraManager.isOpen()) {
  286. Log.w(TAG,
  287. "initCamera() while already open -- late SurfaceView callback?");
  288. return;
  289. }
  290. try {
  291. cameraManager.openDriver(surfaceHolder);
  292. // Creating the handler starts the preview, which can also throw a
  293. // RuntimeException.
  294. if (handler == null) {
  295. handler = new CaptureActivityHandler(this, viewfinderView,
  296. decodeFormats, characterSet, cameraManager);
  297. }
  298. decodeOrStoreSavedBitmap(null, null);
  299. } catch (IOException ioe) {
  300. Log.w(TAG, ioe);
  301. Toast.makeText(this, R.string.camera_problem, Toast.LENGTH_SHORT)
  302. .show();
  303. finish();
  304. } catch (RuntimeException e) {
  305. // Barcode Scanner has seen crashes in the wild of this variety:
  306. // java.?lang.?RuntimeException: Fail to connect to camera service
  307. Log.w(TAG, "Unexpected error initializing camera", e);
  308. Toast.makeText(this, R.string.framwork_problem, Toast.LENGTH_SHORT)
  309. .show();
  310. }
  311. }
  312. public void restartPreviewAfterDelay(long delayMS) {
  313. if (handler != null) {
  314. handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
  315. }
  316. }
  317. public void drawViewfinder() {
  318. viewfinderView.drawViewfinder();
  319. }
  320. }