| | |
| | | package com.hdl.photovoltaic.ui.device; |
| | | |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | import androidx.appcompat.content.res.AppCompatResources; |
| | | |
| | | import android.content.Intent; |
| | | import android.database.Cursor; |
| | | import android.graphics.Rect; |
| | | import android.hardware.Camera; |
| | | import android.net.Uri; |
| | | import android.os.Bundle; |
| | | import android.os.Handler; |
| | | import android.provider.MediaStore; |
| | | import android.text.TextUtils; |
| | | import android.util.Log; |
| | | import android.view.SurfaceHolder; |
| | | import android.view.SurfaceView; |
| | | import android.view.View; |
| | | import android.view.animation.Animation; |
| | | import android.view.animation.TranslateAnimation; |
| | | import android.widget.ImageView; |
| | | import android.widget.RelativeLayout; |
| | | import android.widget.Toast; |
| | | |
| | | 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.google.zxing.common.HybridBinarizer; |
| | | import com.google.zxing.qrcode.QRCodeReader; |
| | | import com.hdl.photovoltaic.R; |
| | | import com.hdl.photovoltaic.base.CustomBaseActivity; |
| | | import com.hdl.photovoltaic.databinding.ActivityFastScanBinding; |
| | | import com.zxing.IZxingActivity; |
| | | import com.zxing.camera.CameraManager; |
| | | import com.zxing.decode.DecodeThread; |
| | | import com.zxing.decode.RGBLuminanceSource; |
| | | import com.zxing.utils.BeepManager; |
| | | import com.zxing.utils.CaptureActivityHandler; |
| | | import com.zxing.utils.InactivityTimer; |
| | | |
| | | public class FastScanActivity extends CustomBaseActivity { |
| | | import java.io.FileNotFoundException; |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Field; |
| | | import java.util.Hashtable; |
| | | |
| | | |
| | | public class FastScanActivity extends CustomBaseActivity implements IZxingActivity, SurfaceHolder.Callback { |
| | | private static final String TAG = com.zxing.qrcode.CaptureActivity.class.getSimpleName(); |
| | | private final int REQUEST_CODE = 33; |
| | | private CameraManager cameraManager; |
| | | private CaptureActivityHandler handler; |
| | | private InactivityTimer inactivityTimer; |
| | | private BeepManager beepManager; |
| | | private SurfaceView scanPreview = null; |
| | | private RelativeLayout scanContainer; |
| | | private RelativeLayout scanCropView; |
| | | private Rect mCropRect = null; |
| | | private boolean isHasSurface = false; |
| | | private ActivityFastScanBinding viewBinding; |
| | | |
| | | @Override |
| | | public Handler getHandler() { |
| | | return handler; |
| | | } |
| | | |
| | | @Override |
| | | public void drawViewfinder() { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public CameraManager getCameraManager() { |
| | | return cameraManager; |
| | | } |
| | | |
| | | @Override |
| | | public Object getContentView() { |
| | |
| | | |
| | | @Override |
| | | public void onBindView(Bundle savedInstanceState) { |
| | | // Window window = getWindow(); |
| | | // window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
| | | // //设置根视图 |
| | | // View mContentView = LayoutInflater.from(this).inflate(R.layout.activity_new_capture, null); |
| | | // setContentView(mContentView); |
| | | //初始化 |
| | | initView(savedInstanceState); |
| | | //初始化界面监听器 |
| | | initEvent(); |
| | | } |
| | | |
| | | |
| | | private void initView(Bundle savedInstanceState) { |
| | | |
| | | |
| | | scanPreview = findViewById(R.id.new_capture_preview); |
| | | scanContainer = findViewById(R.id.new_capture_rl); |
| | | scanCropView = findViewById(R.id.new_capture_crop_view); |
| | | ImageView scanLine = findViewById(R.id.new_capture_scan_line); |
| | | inactivityTimer = new InactivityTimer(this); |
| | | beepManager = new BeepManager(this); |
| | | |
| | | TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation |
| | | .RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, |
| | | 0.9f); |
| | | animation.setDuration(2000); |
| | | animation.setRepeatCount(-1); |
| | | animation.setRepeatMode(Animation.RESTART); |
| | | scanLine.startAnimation(animation); |
| | | } |
| | | |
| | | private void initEvent() { |
| | | viewBinding.newTopBackBtn.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | finish(); |
| | | } |
| | | }); |
| | | |
| | | viewBinding.newTopMoreBtn.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | //跳到入网 |
| | | } |
| | | }); |
| | | |
| | | viewBinding.newLightIv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | v.setSelected(!v.isSelected()); |
| | | if (v.isSelected()) { |
| | | viewBinding.newLightIv.setImageDrawable(AppCompatResources.getDrawable(FastScanActivity.this, com.zxing.R.drawable.fast_scan_light_open)); |
| | | } else { |
| | | viewBinding.newLightIv.setImageDrawable(AppCompatResources.getDrawable(FastScanActivity.this, com.zxing.R.drawable.fast_scan_light_close)); |
| | | } |
| | | flashLightOnOrOff(); |
| | | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | public void enterGallery() { |
| | | // 进入图库 |
| | | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); |
| | | intent.addCategory(Intent.CATEGORY_OPENABLE); |
| | | intent.setType("image/*"); |
| | | intent.putExtra("return-data", true); |
| | | startActivityForResult(intent, REQUEST_CODE); |
| | | } |
| | | |
| | | @Override |
| | | protected void onResume() { |
| | | super.onResume(); |
| | | cameraManager = new CameraManager(getApplication()); |
| | | handler = null; |
| | | if (isHasSurface) { |
| | | initCamera(scanPreview.getHolder()); |
| | | } else { |
| | | scanPreview.getHolder().addCallback(this); |
| | | } |
| | | |
| | | inactivityTimer.onResume(); |
| | | } |
| | | |
| | | @Override |
| | | protected void onPause() { |
| | | if (handler != null) { |
| | | handler.quitSynchronously(); |
| | | handler = null; |
| | | } |
| | | inactivityTimer.onPause(); |
| | | beepManager.close(); |
| | | cameraManager.closeDriver(); |
| | | if (!isHasSurface) { |
| | | scanPreview.getHolder().removeCallback(this); |
| | | } |
| | | super.onPause(); |
| | | } |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | inactivityTimer.shutdown(); |
| | | super.onDestroy(); |
| | | } |
| | | |
| | | @Override |
| | | public void surfaceCreated(SurfaceHolder holder) { |
| | | if (holder == null) { |
| | | Log.d(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!"); |
| | | } |
| | | if (!isHasSurface) { |
| | | isHasSurface = true; |
| | | initCamera(holder); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void surfaceDestroyed(SurfaceHolder holder) { |
| | | isHasSurface = false; |
| | | } |
| | | |
| | | @Override |
| | | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { |
| | | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * A valid barcode has been found, so give an indication of success and show |
| | | * the results. |
| | | * |
| | | * @param rawResult The contents of the barcode. |
| | | * @param bundle The extras |
| | | */ |
| | | @Override |
| | | public void handleDecode(Result rawResult, Bundle bundle) { |
| | | inactivityTimer.onActivity(); |
| | | beepManager.playBeepSoundAndVibrate(); |
| | | doProcess(rawResult.getText()); |
| | | restartPreviewAfterDelay(3000); |
| | | } |
| | | |
| | | private void initCamera(SurfaceHolder surfaceHolder) { |
| | | if (surfaceHolder == null) { |
| | | throw new IllegalStateException("No SurfaceHolder provided"); |
| | | } |
| | | if (cameraManager.isOpen()) { |
| | | Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?"); |
| | | return; |
| | | } |
| | | try { |
| | | cameraManager.openDriver(surfaceHolder); |
| | | // Creating the handler starts the preview, which can also throw a |
| | | // RuntimeException. |
| | | if (handler == null) { |
| | | handler = new CaptureActivityHandler(this, cameraManager, DecodeThread.ALL_MODE); |
| | | } |
| | | |
| | | initCrop(); |
| | | } catch (IOException ioe) { |
| | | Log.w(TAG, ioe); |
| | | Toast.makeText(this, com.zxing.R.string.capture_no_camera, Toast.LENGTH_SHORT).show(); |
| | | finish(); |
| | | } catch (RuntimeException e) { |
| | | Log.w(TAG, "Unexpected error initializing camera", e); |
| | | Toast.makeText(this, com.zxing.R.string.capture_no_camera, Toast.LENGTH_SHORT).show(); |
| | | finish(); |
| | | } |
| | | } |
| | | |
| | | public void restartPreviewAfterDelay(long delayMS) { |
| | | if (handler != null) { |
| | | handler.sendEmptyMessageDelayed(com.zxing.R.id.restart_preview, delayMS); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Rect getCropRect() { |
| | | return mCropRect; |
| | | } |
| | | |
| | | /** |
| | | * 初始化截取的矩形区域 |
| | | */ |
| | | private void initCrop() { |
| | | int cameraWidth = cameraManager.getCameraResolution().y; |
| | | int cameraHeight = cameraManager.getCameraResolution().x; |
| | | |
| | | /** 获取布局中扫描框的位置信息 */ |
| | | int[] location = new int[2]; |
| | | scanCropView.getLocationInWindow(location); |
| | | |
| | | int cropLeft = location[0]; |
| | | int cropTop = location[1] - getStatusBarHeight(); |
| | | |
| | | int cropWidth = scanCropView.getWidth(); |
| | | int cropHeight = scanCropView.getHeight(); |
| | | |
| | | /** 获取布局容器的宽高 */ |
| | | int containerWidth = scanContainer.getWidth(); |
| | | int containerHeight = scanContainer.getHeight(); |
| | | |
| | | /** 计算最终截取的矩形的左上角顶点x坐标 */ |
| | | int x = cropLeft * cameraWidth / containerWidth; |
| | | /** 计算最终截取的矩形的左上角顶点y坐标 */ |
| | | int y = cropTop * cameraHeight / containerHeight; |
| | | |
| | | /** 计算最终截取的矩形的宽度 */ |
| | | int width = cropWidth * cameraWidth / containerWidth; |
| | | /** 计算最终截取的矩形的高度 */ |
| | | int height = cropHeight * cameraHeight / containerHeight; |
| | | |
| | | /** 生成最终的截取的矩形 */ |
| | | mCropRect = new Rect(x, y, width + x, height + y); |
| | | } |
| | | |
| | | private int getStatusBarHeight() { |
| | | try { |
| | | Class<?> c = Class.forName("com.android.internal.R$dimen"); |
| | | Object obj = c.newInstance(); |
| | | Field field = c.getField("status_bar_height"); |
| | | int x = Integer.parseInt(field.get(obj).toString()); |
| | | return getResources().getDimensionPixelSize(x); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | private void doProcess(String result) { |
| | | Log.d("panlili", "scanResult: " + result); |
| | | /*if (!DeviceHelper.getNetworkState()) { |
| | | Toast.makeText(this, R.string.capture_no_network, Toast.LENGTH_SHORT).show(); |
| | | return; |
| | | }*/ |
| | | |
| | | if (TextUtils.isEmpty(result)) { |
| | | Toast.makeText(this, com.zxing.R.string.capture_no_result, Toast.LENGTH_SHORT).show(); |
| | | } else { |
| | | Intent intent = new Intent(); |
| | | intent.putExtra("data", result); |
| | | setResult(RESULT_OK, intent); |
| | | finish(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onActivityResult(int requestCode, int resultCode, Intent data) { |
| | | super.onActivityResult(requestCode, resultCode, data); |
| | | if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) { |
| | | Uri originalUri = data.getData(); |
| | | if (originalUri != null) { |
| | | String path = originalUri.getPath(); |
| | | String[] proj = {MediaStore.Images.Media.DATA}; |
| | | Cursor cursor = getContentResolver().query(originalUri, proj, null, null, null); |
| | | if (cursor != null) { |
| | | int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); |
| | | cursor.moveToFirst(); |
| | | path = cursor.getString(column_index); |
| | | cursor.close(); |
| | | } |
| | | |
| | | if (!TextUtils.isEmpty(path)) { |
| | | handleQRCodeFormPhoto(path); |
| | | } else { |
| | | Toast.makeText(this, "图片已损坏,请重新选择!", Toast.LENGTH_SHORT).show(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 解析图库选择的二维码 |
| | | */ |
| | | public void handleQRCodeFormPhoto(final String filePath) { |
| | | Thread dealThread = new Thread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | Hashtable<DecodeHintType, String> hints = new Hashtable<>(); |
| | | hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); |
| | | RGBLuminanceSource source = null; |
| | | try { |
| | | source = new RGBLuminanceSource(filePath); |
| | | } catch (FileNotFoundException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); |
| | | QRCodeReader reader = new QRCodeReader(); |
| | | Result result; |
| | | try { |
| | | result = reader.decode(binaryBitmap, hints); |
| | | if (!TextUtils.isEmpty(result.getText())) { |
| | | dealUIInfo(result.getText()); |
| | | } else { |
| | | dealUIInfo(null); |
| | | } |
| | | } catch (NotFoundException | ChecksumException | FormatException e) { |
| | | dealUIInfo(null); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }); |
| | | dealThread.start(); |
| | | } |
| | | |
| | | private void dealUIInfo(final Object progressInfo) { |
| | | runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | if (progressInfo == null) { |
| | | Toast.makeText(FastScanActivity.this, com.zxing.R.string.capture_no_result2, Toast.LENGTH_SHORT).show(); |
| | | } else { |
| | | doProcess(progressInfo.toString()); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 闪光灯开启或者关闭 |
| | | */ |
| | | private void flashLightOnOrOff() { |
| | | // |
| | | android.hardware.Camera camera = cameraManager.getCamera(); |
| | | if (camera == null) { |
| | | return; |
| | | } |
| | | android.hardware.Camera.Parameters parameters = camera.getParameters(); |
| | | // 判断闪光灯当前状态 |
| | | if (Camera.Parameters.FLASH_MODE_OFF.equals(parameters.getFlashMode())) { |
| | | onLight(camera, parameters); |
| | | } else if (Camera.Parameters.FLASH_MODE_TORCH.equals(parameters.getFlashMode())) { |
| | | offLight(camera, parameters); |
| | | } |
| | | } |
| | | |
| | | private void onLight(android.hardware.Camera camera, Camera.Parameters parameters) { |
| | | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); |
| | | camera.setParameters(parameters); |
| | | } |
| | | |
| | | private void offLight(android.hardware.Camera camera, Camera.Parameters parameters) { |
| | | parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); |
| | | camera.setParameters(parameters); |
| | | } |
| | | |
| | | |
| | | } |