package com.lzx.lock.module.camera; import android.Manifest; import android.app.Fragment; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.AudioAttributes; import android.media.Image; import android.media.ImageReader; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.util.Log; import android.util.Range; import android.util.Size; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import com.lzx.lock.R; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collections; public class Camera2Fragment extends Fragment { private static final String TAG = "Camera2Fragment"; private static final int SETIMAGE = 1; private static final int MOVE_FOCK = 2; TextureView mTextureView; ImageView mThumbnail; Button mButton; Handler mHandler; Handler mUIHandler; ImageReader mImageReader; CaptureRequest.Builder mPreViewBuidler; CameraCaptureSession mCameraSession; CameraCharacteristics mCameraCharacteristics; Ringtone ringtone; //相机会话的监听器,通过他得到mCameraSession对象,这个对象可以用来发送预览和拍照请求 private CameraCaptureSession.StateCallback mSessionStateCallBack = new CameraCaptureSession .StateCallback() { @Override public void onConfigured(CameraCaptureSession cameraCaptureSession) { try { mCameraSession = cameraCaptureSession; cameraCaptureSession.setRepeatingRequest(mPreViewBuidler.build(), null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { } }; private Surface surface; //打开相机时候的监听器,通过他可以得到相机实例,这个实例可以创建请求建造者 private CameraDevice.StateCallback cameraOpenCallBack = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice cameraDevice) { Log.d(TAG, "相机已经打开"); try { mPreViewBuidler = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); SurfaceTexture texture = mTextureView.getSurfaceTexture(); texture.setDefaultBufferSize(mPreViewSize.getWidth(), mPreViewSize.getHeight()); surface = new Surface(texture); mPreViewBuidler.addTarget(surface); cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface ()), mSessionStateCallBack, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(CameraDevice cameraDevice) { Log.d(TAG, "相机连接断开"); } @Override public void onError(CameraDevice cameraDevice, int i) { Log.d(TAG, "相机打开失败"); } }; private ImageReader.OnImageAvailableListener onImageAvaiableListener = new ImageReader .OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader imageReader) { mHandler.post(new ImageSaver(imageReader.acquireNextImage())); } }; private Size mPreViewSize; private Rect maxZoomrect; private int maxRealRadio; //预览图显示控件的监听器,可以监听这个surface的状态 private TextureView.SurfaceTextureListener mSurfacetextlistener = new TextureView .SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { HandlerThread thread = new HandlerThread("Ceamera3"); thread.start(); mHandler = new Handler(thread.getLooper()); CameraManager manager = (CameraManager) getActivity().getSystemService(Context .CAMERA_SERVICE); String cameraid = CameraCharacteristics.LENS_FACING_FRONT + ""; try { mCameraCharacteristics = manager.getCameraCharacteristics(cameraid); //画面传感器的面积,单位是像素。 maxZoomrect = mCameraCharacteristics.get(CameraCharacteristics .SENSOR_INFO_ACTIVE_ARRAY_SIZE); //最大的数字缩放 maxRealRadio = mCameraCharacteristics.get(CameraCharacteristics .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM).intValue(); picRect = new Rect(maxZoomrect); StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics .SCALER_STREAM_CONFIGURATION_MAP); Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG) ), new CompareSizeByArea()); mPreViewSize = map.getOutputSizes(SurfaceTexture.class)[0]; mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, 5); mImageReader.setOnImageAvailableListener(onImageAvaiableListener, mHandler); if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } manager.openCamera(cameraid, cameraOpenCallBack, mHandler); //设置点击拍照的监听 mButton.setOnTouchListener(onTouchListener); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } }; private View.OnTouchListener onTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: try { mCameraSession.setRepeatingRequest(initDngBuilder().build(), null, mHandler); } catch (CameraAccessException e) { Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show(); } break; case MotionEvent.ACTION_UP: try { updateCameraPreviewSession(); } catch (CameraAccessException e) { Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show(); } break; } return true; } }; private void updateCameraPreviewSession() throws CameraAccessException { mPreViewBuidler.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL); mPreViewBuidler.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); mCameraSession.setRepeatingRequest(mPreViewBuidler.build(), null, mHandler); } /** * 设置连拍的参数 * * @return */ private CaptureRequest.Builder initDngBuilder() { CaptureRequest.Builder captureBuilder = null; try { captureBuilder = mCameraSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureBuilder.addTarget(mImageReader.getSurface()); captureBuilder.addTarget(surface); // Required for RAW capture captureBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON); captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); captureBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, (long) ((214735991 - 13231) / 2)); captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0); captureBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, (10000 - 100) / 2);//设置 ISO,感光度 captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 90); //设置每秒30帧 CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE); String cameraid = CameraCharacteristics.LENS_FACING_FRONT + ""; CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraid); Range<Integer> fps[] = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); captureBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fps[fps.length - 1]); } catch (CameraAccessException e) { Toast.makeText(getActivity(), "请求相机权限被拒绝", Toast.LENGTH_SHORT).show(); } catch (NullPointerException e) { Toast.makeText(getActivity(), "打开相机失败", Toast.LENGTH_SHORT).show(); } return captureBuilder; } private View.OnClickListener picOnClickListener = new View.OnClickListener() { @Override public void onClick(View view) { try { shootSound(); Log.d(TAG, "正在拍照"); CaptureRequest.Builder builder = mCameraSession.getDevice().createCaptureRequest (CameraDevice.TEMPLATE_STILL_CAPTURE); builder.addTarget(mImageReader.getSurface()); builder.set(CaptureRequest.SCALER_CROP_REGION, picRect); builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_EDOF); // builder.set(CaptureRequest.CONTROL_AF_TRIGGER, // CameraMetadata.CONTROL_AF_TRIGGER_START); builder.set(CaptureRequest.JPEG_ORIENTATION, 90); mCameraSession.capture(builder.build(), null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } }; private View.OnTouchListener textTureOntuchListener = new View.OnTouchListener() { //时时当前的zoom public double zoom; // 0<缩放比<mCameraCharacteristics.get(CameraCharacteristics // .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM).intValue(); //上次缩放前的zoom public double lastzoom; //两个手刚一起碰到手机屏幕的距离 public double lenth; int count; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: count = 1; break; case MotionEvent.ACTION_MOVE: if (count >= 2) { float x1 = event.getX(0); float y1 = event.getY(0); float x2 = event.getX(1); float y2 = event.getY(1); float x = x1 - x2; float y = y1 - y2; Double lenthRec = Math.sqrt(x * x + y * y) - lenth; Double viewLenth = Math.sqrt(v.getWidth() * v.getWidth() + v.getHeight() * v.getHeight()); zoom = ((lenthRec / viewLenth) * maxRealRadio) + lastzoom; picRect.top = (int) (maxZoomrect.top / (zoom)); picRect.left = (int) (maxZoomrect.left / (zoom)); picRect.right = (int) (maxZoomrect.right / (zoom)); picRect.bottom = (int) (maxZoomrect.bottom / (zoom)); Message.obtain(mUIHandler, MOVE_FOCK).sendToTarget(); } break; case MotionEvent.ACTION_UP: count = 0; break; case MotionEvent.ACTION_POINTER_DOWN: count++; if (count == 2) { float x1 = event.getX(0); float y1 = event.getY(0); float x2 = event.getX(1); float y2 = event.getY(1); float x = x1 - x2; float y = y1 - y2; lenth = Math.sqrt(x * x + y * y); } break; case MotionEvent.ACTION_POINTER_UP: count--; if (count < 2) lastzoom = zoom; break; } return true; } }; //相机缩放相关 private Rect picRect; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_camera2, null); findview(v); mUIHandler = new Handler(new InnerCallBack()); //初始化拍照的声音 ringtone = RingtoneManager.getRingtone(getActivity(), Uri.parse ("file:///system/media/audio/ui/camera_click.ogg")); AudioAttributes.Builder attr = new AudioAttributes.Builder(); attr.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION); ringtone.setAudioAttributes(attr.build()); //初始化相机布局 mTextureView.setSurfaceTextureListener(mSurfacetextlistener); mTextureView.setOnTouchListener(textTureOntuchListener); return v; } @Override public void onDestroyView() { super.onDestroyView(); if (mCameraSession != null) { mCameraSession.getDevice().close(); mCameraSession.close(); } } private void findview(View v) { mTextureView = (TextureView) v.findViewById(R.id.tv_textview); mButton = (Button) v.findViewById(R.id.btn_takepic); mThumbnail = (ImageView) v.findViewById(R.id.iv_Thumbnail); mThumbnail.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(), "别戳了,那个页面还没写", Toast.LENGTH_SHORT).show(); } }); } /** * 播放系统的拍照的声音 */ public void shootSound() { ringtone.stop(); ringtone.play(); } private class ImageSaver implements Runnable { Image reader; public ImageSaver(Image reader) { this.reader = reader; } @Override public void run() { Log.d(TAG, "正在保存图片"); File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) .getAbsoluteFile(); if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, System.currentTimeMillis() + ".jpg"); FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); ByteBuffer buffer = reader.getPlanes()[0].getBuffer(); byte[] buff = new byte[buffer.remaining()]; buffer.get(buff); BitmapFactory.Options ontain = new BitmapFactory.Options(); ontain.inSampleSize = 50; Bitmap bm = BitmapFactory.decodeByteArray(buff, 0, buff.length, ontain); Message.obtain(mUIHandler, SETIMAGE, bm).sendToTarget(); outputStream.write(buff); Log.d(TAG, "保存图片完成"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } private class InnerCallBack implements Handler.Callback { @Override public boolean handleMessage(Message message) { switch (message.what) { case SETIMAGE: Bitmap bm = (Bitmap) message.obj; mThumbnail.setImageBitmap(bm); break; case MOVE_FOCK: mPreViewBuidler.set(CaptureRequest.SCALER_CROP_REGION, picRect); try { mCameraSession.setRepeatingRequest(mPreViewBuidler.build(), null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } break; } return false; } } }