|
|
package com.geogle.zxing.activity;
|
|
|
|
|
|
import android.app.ProgressDialog;
|
|
|
import android.content.Intent;
|
|
|
import android.content.res.AssetFileDescriptor;
|
|
|
import android.graphics.Bitmap;
|
|
|
import android.media.AudioManager;
|
|
|
import android.media.MediaPlayer;
|
|
|
import android.media.MediaPlayer.OnCompletionListener;
|
|
|
import android.net.Uri;
|
|
|
import android.os.Bundle;
|
|
|
import android.os.Handler;
|
|
|
import android.os.Vibrator;
|
|
|
|
|
|
import android.text.TextUtils;
|
|
|
import android.view.SurfaceHolder;
|
|
|
import android.view.SurfaceHolder.Callback;
|
|
|
import android.view.SurfaceView;
|
|
|
import android.view.View;
|
|
|
import android.widget.Button;
|
|
|
import android.widget.ImageButton;
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
|
|
|
|
import com.google.zxing.BarcodeFormat;
|
|
|
import com.google.zxing.BinaryBitmap;
|
|
|
import com.google.zxing.ChecksumException;
|
|
|
import com.google.zxing.DecodeHintType;
|
|
|
import com.google.zxing.FormatException;
|
|
|
import com.google.zxing.NotFoundException;
|
|
|
import com.google.zxing.Result;
|
|
|
import com.geogle.zxing.camera.CameraManager;
|
|
|
import com.google.zxing.common.HybridBinarizer;
|
|
|
|
|
|
import com.geogle.zxing.decoding.InactivityTimer;
|
|
|
import com.geogle.zxing.decoding.RGBLuminanceSource;
|
|
|
import com.google.zxing.qrcode.QRCodeReader;
|
|
|
import com.geogle.zxing.view.ViewfinderView;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.util.Hashtable;
|
|
|
import java.util.Vector;
|
|
|
|
|
|
import com.geogle.zxing.decoding.CaptureActivityHandler;
|
|
|
import edu.hzuapps.androidlabs.R;
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Initial the camera
|
|
|
*
|
|
|
* @author Ryan.Tang
|
|
|
*/
|
|
|
public class CaptureActivity extends AppCompatActivity implements Callback {
|
|
|
|
|
|
private static final int REQUEST_CODE_SCAN_GALLERY = 100;
|
|
|
|
|
|
private CaptureActivityHandler handler;
|
|
|
private ViewfinderView viewfinderView;
|
|
|
private ImageButton back;
|
|
|
private ImageButton btnFlash;
|
|
|
private Button btnAlbum; // 相册
|
|
|
private boolean isFlashOn = false;
|
|
|
private boolean hasSurface;
|
|
|
private Vector<BarcodeFormat> decodeFormats;
|
|
|
private String characterSet;
|
|
|
private InactivityTimer inactivityTimer;
|
|
|
private MediaPlayer mediaPlayer;
|
|
|
private boolean playBeep;
|
|
|
private static final float BEEP_VOLUME = 0.10f;
|
|
|
private boolean vibrate;
|
|
|
private ProgressDialog mProgress;
|
|
|
private String photo_path;
|
|
|
private Bitmap scanBitmap;
|
|
|
// private Button cancelScanButton;
|
|
|
/**
|
|
|
* Called when the activity is first created.
|
|
|
*/
|
|
|
@Override
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
super.onCreate(savedInstanceState);
|
|
|
setContentView(R.layout.activity_scanner);
|
|
|
//ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);
|
|
|
CameraManager.init(getApplication());
|
|
|
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_content);
|
|
|
back = (ImageButton) findViewById(R.id.btn_back);
|
|
|
back.setOnClickListener(new View.OnClickListener() {
|
|
|
@Override
|
|
|
public void onClick(View v) {
|
|
|
finish();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
btnFlash = (ImageButton) findViewById(R.id.btn_flash);
|
|
|
btnFlash.setOnClickListener(flashListener);
|
|
|
|
|
|
btnAlbum = (Button) findViewById(R.id.btn_album);
|
|
|
btnAlbum.setOnClickListener(albumOnClick);
|
|
|
|
|
|
// cancelScanButton = (Button) this.findViewById(R.id.btn_cancel_scan);
|
|
|
hasSurface = false;
|
|
|
inactivityTimer = new InactivityTimer(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
private View.OnClickListener albumOnClick = new View.OnClickListener() {
|
|
|
@Override
|
|
|
public void onClick(View view) {
|
|
|
//打开手机中的相册
|
|
|
Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); //"android.intent.action.GET_CONTENT"
|
|
|
innerIntent.setType("image/*");
|
|
|
startActivityForResult(innerIntent, REQUEST_CODE_SCAN_GALLERY);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
|
|
|
@Override
|
|
|
protected void onActivityResult(final int requestCode, int resultCode, Intent data) {
|
|
|
if (resultCode==RESULT_OK) {
|
|
|
switch (requestCode) {
|
|
|
case REQUEST_CODE_SCAN_GALLERY:
|
|
|
handleAlbumPic(data);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 处理选择的图片
|
|
|
* @param data
|
|
|
*/
|
|
|
private void handleAlbumPic(Intent data) {
|
|
|
//获取选中图片的路径
|
|
|
final Uri uri = data.getData();
|
|
|
|
|
|
mProgress = new ProgressDialog(CaptureActivity.this);
|
|
|
mProgress.setMessage("正在扫描...");
|
|
|
mProgress.setCancelable(false);
|
|
|
mProgress.show();
|
|
|
|
|
|
runOnUiThread(new Runnable() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
Result result = scanningImage(uri);
|
|
|
mProgress.dismiss();
|
|
|
if (result != null) {
|
|
|
Intent resultIntent = new Intent();
|
|
|
Bundle bundle = new Bundle();
|
|
|
bundle.putString(com.dommy.qrcode.util.Constant.INTENT_EXTRA_KEY_QR_SCAN ,result.getText());
|
|
|
|
|
|
resultIntent.putExtras(bundle);
|
|
|
CaptureActivity.this.setResult(RESULT_OK, resultIntent);
|
|
|
finish();
|
|
|
} else {
|
|
|
Toast.makeText(CaptureActivity.this, "识别失败", Toast.LENGTH_SHORT).show();
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 扫描二维码图片的方法
|
|
|
* @param uri
|
|
|
* @return
|
|
|
*/
|
|
|
public Result scanningImage(Uri uri) {
|
|
|
if (uri == null) {
|
|
|
return null;
|
|
|
}
|
|
|
Hashtable<DecodeHintType, String> hints = new Hashtable<>();
|
|
|
hints.put(DecodeHintType.CHARACTER_SET, "UTF8"); //设置二维码内容的编码
|
|
|
|
|
|
scanBitmap = com.dommy.qrcode.util.BitmapUtil.decodeUri(this, uri, 500, 500);
|
|
|
RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap);
|
|
|
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
|
|
|
QRCodeReader reader = new QRCodeReader();
|
|
|
try {
|
|
|
return reader.decode(bitmap1, hints);
|
|
|
} catch (NotFoundException e) {
|
|
|
e.printStackTrace();
|
|
|
} catch (ChecksumException e) {
|
|
|
e.printStackTrace();
|
|
|
} catch (FormatException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void onResume() {
|
|
|
super.onResume();
|
|
|
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.scanner_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;
|
|
|
|
|
|
//quit the scan view
|
|
|
// cancelScanButton.setOnClickListener(new OnClickListener() {
|
|
|
//
|
|
|
// @Override
|
|
|
// public void onClick(View v) {
|
|
|
// CaptureActivity.this.finish();
|
|
|
// }
|
|
|
// });
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void onPause() {
|
|
|
super.onPause();
|
|
|
if (handler != null) {
|
|
|
handler.quitSynchronously();
|
|
|
handler = null;
|
|
|
}
|
|
|
CameraManager.get().closeDriver();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void onDestroy() {
|
|
|
inactivityTimer.shutdown();
|
|
|
super.onDestroy();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Handler scan result
|
|
|
*
|
|
|
* @param result
|
|
|
* @param barcode
|
|
|
*/
|
|
|
public void handleDecode(Result result, Bitmap barcode) {
|
|
|
inactivityTimer.onActivity();
|
|
|
playBeepSoundAndVibrate();
|
|
|
String resultString = result.getText();
|
|
|
//FIXME
|
|
|
if (TextUtils.isEmpty(resultString)) {
|
|
|
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
|
|
|
} else {
|
|
|
Intent resultIntent = new Intent();
|
|
|
Bundle bundle = new Bundle();
|
|
|
bundle.putString(com.dommy.qrcode.util.Constant.INTENT_EXTRA_KEY_QR_SCAN, resultString);
|
|
|
System.out.println("sssssssssssssssss scan 0 = " + resultString);
|
|
|
// 不能使用Intent传递大于40kb的bitmap,可以使用一个单例对象存储这个bitmap
|
|
|
// bundle.putParcelable("bitmap", barcode);
|
|
|
// Logger.d("saomiao",resultString);
|
|
|
resultIntent.putExtras(bundle);
|
|
|
this.setResult(RESULT_OK, resultIntent);
|
|
|
}
|
|
|
CaptureActivity.this.finish();
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@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 viewfinderView;
|
|
|
}
|
|
|
|
|
|
public Handler getHandler() {
|
|
|
return handler;
|
|
|
}
|
|
|
|
|
|
public void drawViewfinder() {
|
|
|
viewfinderView.drawViewfinder();
|
|
|
|
|
|
}
|
|
|
|
|
|
private void 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;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* When the beep has finished playing, rewind to queue up another one.
|
|
|
*/
|
|
|
private final OnCompletionListener beepListener = new OnCompletionListener() {
|
|
|
public void onCompletion(MediaPlayer mediaPlayer) {
|
|
|
mediaPlayer.seekTo(0);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 闪光灯开关按钮
|
|
|
*/
|
|
|
private View.OnClickListener flashListener = new View.OnClickListener() {
|
|
|
@Override
|
|
|
public void onClick(View view) {
|
|
|
try {
|
|
|
boolean isSuccess = CameraManager.get().setFlashLight(!isFlashOn);
|
|
|
if(!isSuccess){
|
|
|
Toast.makeText(CaptureActivity.this, "暂时无法开启闪光灯", Toast.LENGTH_SHORT).show();
|
|
|
return;
|
|
|
}
|
|
|
if (isFlashOn) {
|
|
|
// 关闭闪光灯
|
|
|
btnFlash.setImageResource(R.drawable.flash_off);
|
|
|
isFlashOn = false;
|
|
|
} else {
|
|
|
// 开启闪光灯
|
|
|
btnFlash.setImageResource(R.drawable.flash_on);
|
|
|
isFlashOn = true;
|
|
|
}
|
|
|
}catch (Exception e){
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
} |