这是我第一次尝试使用Camera2Api访问和点击图像。 我正在使用在API 23上运行的Nexus 5。 虽然我可以获得相机预览,但我无法理解为什么在捕获请求之后帧被锁定,并且生成的图像模糊/完全不清楚。 我现在已经坚持这个问题一段时间了。任何建议将不胜感激 附件是我的MainActivity代码: -
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0,90); ORIENTATIONS.append(Surface.ROTATION_90,0); ORIENTATIONS.append(Surface.ROTATION_180,270); ORIENTATIONS.append(Surface.ROTATION_270,180); } private static final String TAG = "MainActivity"; private static final int STATE_PREVIEW=0; private static final int STATE_WAIT_AF_LOCK=1; private static final int STATE_PICTURE_CAPTURED=2; private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0; private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT = 1; private static final int REQUEST_READ_EXTERNAL_STORAGE_REQUEST = 2; private int mState; private static LruCache<String, Bitmap> mMemoryCache; private HandlerThread mBackgroundThread; private final Handler mUIHandler = new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg){ swapImageAdapter(); } }; private static File mImageFile; private Handler mBackgroundHandler; private TextureView mTextureView; private Button mCaptureButton; private File mImageFolder; private static String mImageFileName; private Size mPreviewSize; //mImageSize private RecyclerView mRecycleView; private String mCameraId; private CameraDevice mCameraDevice; private CaptureRequest mPreviewCaptureRequest; private CaptureRequest.Builder mPreviewCaptureRequestBuilder; private CameraCaptureSession mCameraCaptureSession; private ImageReader mImageReader; private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener(){ @Override public void onImageAvailable(ImageReader reader){ Log.i(TAG,"OnImageAvailableListener!!!"); mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(),mUIHandler)); } }; private static class ImageSaver implements Runnable{ private final Image mImage; private final Handler mHandler; ImageSaver(Image image){ Log.i(TAG,"imgSaver const"); mImage=image; mHandler=null; } ImageSaver(Image image,Handler handler){ Log.i(TAG,"imgSaver const"); mImage =image; mHandler =handler; } @Override public void run(){ Log.i(TAG,"In ImageSaver run()"); ByteBuffer byteBuffer=mImage.getPlanes()[0].getBuffer(); byteBuffer.rewind(); byte[] bytes = new byte[byteBuffer.capacity()]; byteBuffer.get(bytes); FileOutputStream fileOutputStream = null; try{ fileOutputStream =new FileOutputStream(mImageFileName); fileOutputStream.write(bytes); }catch(IOException e){ e.printStackTrace(); } finally{ Log.i(TAG,"Closing Image!!"); mImage.close(); if(fileOutputStream!=null){ try { fileOutputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } Message message = mHandler.obtainMessage(); Log.i(TAG,"sending Message from Image Saver run()"); message.sendToTarget(); } } private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); Log.i(TAG,"mSessionCaptureCallback+ onCaptureStarted"); } @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result){ super.onCaptureCompleted(session,request,result); Log.i(TAG,"mSessionCaptureCallback+ onCaptureCompleted"); process(result); //process the result once capture session request is completed. Log.i(TAG,"mSessionCaptureCallback+ onCaptureCompleted ENDS!"); } @Override public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure){ super.onCaptureFailed(session, request, failure); Toast.makeText(getApplicationContext(),"Focus Lock UnSucessfull!", Toast.LENGTH_SHORT).show(); } private void process(CaptureResult result){ Log.i(TAG,"mSTATE_PICTURE_CAPTURED"+mState); switch (mState){ case STATE_PREVIEW: break; case STATE_WAIT_AF_LOCK: Log.i(TAG,"process_ wait_AF_LOCK"); Integer afState=result.get(CaptureResult.CONTROL_AF_STATE); if(afState==CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED){ Log.i(TAG,"Lock Sucessfull!"); Toast.makeText(getApplicationContext(),"Lock Sucessfull!", Toast.LENGTH_SHORT).show(); mState=STATE_PICTURE_CAPTURED; captureStillImage(); } Log.i(TAG,"Out of process_WAIT_AF_LOCK"); break; case STATE_PICTURE_CAPTURED: break; } } }; private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice cameraDevice) { Log.i(TAG,"CameraDeviceStateCallback+ onOpened"); mCameraDevice = cameraDevice; Toast.makeText(getApplicationContext(), "Cam Opened!", Toast.LENGTH_SHORT).show(); createCameraPreviewSession(); } @Override public void onClosed(CameraDevice dev){ mCameraDevice=null; } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { Log.i(TAG,"CameraDeviceStateCallback+ onDisconnected"); cameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice cameraDevice, int error) { cameraDevice.close(); mCameraDevice = null; Log.i(TAG, "Error Number:" + error + "While opening camera!!!"); } }; private TextureView.SurfaceTextureListener mSurfaceTexture = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { Log.i(TAG, "SurfaceTexture Available"); setupCamera(width, height); Log.i(TAG, "in onSurfaceTextureAvailable "); transformImage(width, height); Log.i(TAG, "in onSurfaceTextureAvailable "); openCamera(); Log.i(TAG, "in onSurfaceTextureAvailable "); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { Log.i(TAG, "in onSurfaceTextureSizeChanged "); } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { Log.i(TAG, "in onSurfaceTextureTextureUpdated"); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.i(TAG, "SurfaceTexture Destroyed"); return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); createImageFolder(); setContentView(R.layout.activity_main); if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED) { mRecycleView = (RecyclerView) findViewById(R.id.galleryRecyclerView); GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 1); mRecycleView.setLayoutManager(gridLayoutManager); RecyclerView.Adapter imageAdapter = new ImageAdapter(mImageFolder); Log.i(TAG, "RecyclerViewSetup!"); mTextureView = (TextureView) findViewById(R.id.textureView); Log.i(TAG, "TextureViewSetup!"); mCaptureButton = (Button) findViewById(R.id.captureButton); mCaptureButton.setOnClickListener(this); } else{ if(shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_READ_EXTERNAL_STORAGE_REQUEST); } } Log.i(TAG,"onCreate Completed"); } @Override public void onResume() { super.onResume(); openBackgroundThread(); if (mTextureView.isAvailable()) { setupCamera(mTextureView.getWidth(), mTextureView.getHeight()); transformImage(mTextureView.getWidth(),mTextureView.getHeight()); if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { openCamera(); } else { if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { Toast.makeText(this, "App needs to be able to save Images", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT); } } else { mTextureView.setSurfaceTextureListener(mSurfaceTexture); } } @Override public void onPause() { closeCamera(); closeBackgroundThread(); super.onPause(); } public void setupCamera(int width, int height) { Log.i(TAG,"setupcam"); CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { for (String cameraId : cameraManager.getCameraIdList()) { CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { continue; } StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size largestImageSize = Collections.max( Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() { @Override public int compare(Size size, Size t1) { return Long.signum(size.getWidth()*size.getHeight()- t1.getWidth()*t1.getHeight()); } } ); mImageReader = ImageReader.newInstance(largestImageSize.getWidth(),largestImageSize.getHeight(),ImageFormat.JPEG,1); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener,mBackgroundHandler); mPreviewSize = getPrefferedPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height); mCameraId = cameraId; Log.i(TAG,"Setup Camera Ends!!"); return; } } catch (CameraAccessException e) { e.printStackTrace(); } } private Size getPrefferedPreviewSize(Size[] mapSizes, int width, int height) { List<Size> collectorSizes = new ArrayList<>(); for (Size size : mapSizes) { if (width > height) { if (size.getWidth() > width && size.getHeight() > height) { collectorSizes.add(size); } else { if (size.getWidth() > height && size.getHeight() > width) { collectorSizes.add(size); } } } } if (collectorSizes.size() > 0) { return Collections.min(collectorSizes, new Comparator<Size>() { @Override public int compare(Size lhs, Size rhs) { return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth()); } }); } return mapSizes[0]; } public void openCamera() { Log.i(TAG,"In OpenCamera"); CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE); try { Log.i(TAG,"CamaeraManager.OpenCamera"); cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); Log.i(TAG,"CamaeraManager.OpenCameraEnds"); } catch(SecurityException s){ s.printStackTrace(); } catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"OpenCamera Ends"); } public void closeCamera(){ if(mImageReader!=null){ mImageReader.close(); mImageReader=null; } if(mCameraCaptureSession!=null) { mCameraCaptureSession.close(); mCameraCaptureSession = null; } if(mCameraDevice!=null){ mCameraDevice.close(); mCameraDevice = null; } } public void createCameraPreviewSession(){ try{ Log.i(TAG,"CREATE_PREVIEW_CAMERA_SESSION"); SurfaceTexture surfaceTexture=mTextureView.getSurfaceTexture(); surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight()); Surface previewSurface = new Surface(surfaceTexture); mPreviewCaptureRequestBuilder=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewCaptureRequestBuilder.addTarget(previewSurface); mCameraDevice.createCaptureSession( Arrays.asList(previewSurface,mImageReader.getSurface()), new CameraCaptureSession.StateCallback(){ @Override public void onConfigured(CameraCaptureSession session){ Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigured"); if(null == mCameraDevice){ return; } try{ mPreviewCaptureRequest=mPreviewCaptureRequestBuilder.build(); mCameraCaptureSession = session; mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequest,mSessionCaptureCallback,mBackgroundHandler); } catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigured setRepeatingRequests"); } @Override public void onConfigureFailed(CameraCaptureSession session){ Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigurationFailed"); Toast.makeText(getApplicationContext(),"CreateCameraSession FAILED!!",Toast.LENGTH_SHORT).show(); } } ,null); }catch(CameraAccessException e){ e.printStackTrace(); } } private void clickPic(){ Log.i(TAG,"in ClickPic"); lockFocus(); Log.i(TAG,"exiting ClickPic"); } private void lockFocus(){ try { Log.i(TAG,"lockFocus"); mState = STATE_WAIT_AF_LOCK; mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,CaptureRequest.CONTROL_AF_TRIGGER_START); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(), mSessionCaptureCallback, mBackgroundHandler); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"exiting lockFocus"); } private void unlockFocus(){ try { Log.i(TAG,"unlockFocus"); mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),mSessionCaptureCallback,mBackgroundHandler); mState = STATE_PREVIEW; mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequestBuilder.build(), mSessionCaptureCallback, mBackgroundHandler); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"exiting lockFocus"); } private void openBackgroundThread(){ mBackgroundThread=new HandlerThread("Camera Background Thread"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { public void handleMessage(Message msg) { Log.i(TAG,"Inside Background Handler"); } }; } private void closeBackgroundThread(){ Log.i(TAG,"closing Background Thread!"); mBackgroundThread.quitSafely(); try{ mBackgroundThread.join(); mBackgroundThread = null; mBackgroundHandler = null; }catch(InterruptedException e){ e.printStackTrace(); } } private void captureStillImage(){ try { Log.i(TAG,"captureStillImage"); mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); mPreviewCaptureRequestBuilder.addTarget(mImageReader.getSurface()); int rotation = getWindowManager().getDefaultDisplay().getRotation(); mPreviewCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation)); CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback(){ @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result){ Log.i(TAG,"captureStillImage+ onCaptureCompleted"+mImageFileName); Toast.makeText(getApplicationContext(),"Image Captured!",Toast.LENGTH_SHORT).show(); unlockFocus(); } public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); Log.i(TAG,"captureStillImage+ onCapturestarted"); try { mImageFile=createImageFileName(); } catch (IOException e) { e.printStackTrace(); } } }; CameraCaptureSession.stopRepeating(); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),captureCallback,null); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"captureStillImage Ends!"); } private void transformImage(int width,int height){ Matrix matrix = new Matrix(); if(mPreviewSize==null||mTextureView==null) { return; } int rotation = getWindowManager().getDefaultDisplay().getRotation(); RectF textureRectF = new RectF(0,0,width,height); RectF previewRectF = new RectF(0,0,mPreviewSize.getHeight(),mPreviewSize.getWidth()); float centerX = textureRectF.centerX(); float centerY = textureRectF.centerY(); if(rotation==Surface.ROTATION_90||rotation==Surface.ROTATION_270){ previewRectF.offset(centerX - previewRectF.centerX(),centerY-previewRectF.centerY()); matrix.setRectToRect(textureRectF,previewRectF,Matrix.ScaleToFit.FILL); float scale = Math.max((float)width/mPreviewSize.getWidth(), (float)height/mPreviewSize.getHeight()); matrix.postScale(scale,scale,centerX,centerY); matrix.postRotate(90*(rotation-2),centerX,centerY); } mTextureView.setTransform(matrix); } @Override public void onClick(View view){ switch(view.getId()){ case R.id.captureButton: clickPic(); break; } } private void checkPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { try { createImageFileName(); } catch (IOException e) { e.printStackTrace(); } } else { if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, "App needs to be able to save Images", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT); } } private void createImageFolder() { Log.i(TAG,"createImageFolder"); File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); mImageFolder = new File(imageFile, "camera2Api"); if(!mImageFolder.exists()) { mImageFolder.mkdirs(); } } private File createImageFileName() throws IOException { Log.i(TAG,"createImageFileName"); String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String prepend = "IMG_" + timestamp + "_"; File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder); mImageFileName = imageFile.getAbsolutePath(); Log.i(TAG,"Image FILE NAME="+mImageFileName); return imageFile; } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) { if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "Application will not run without camera services", Toast.LENGTH_SHORT).show(); } } if(requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Permission successfully granted!", Toast.LENGTH_SHORT).show(); } } if(requestCode==REQUEST_READ_EXTERNAL_STORAGE_REQUEST){ if(grantResults[0]==PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "Permission successfully granted!", Toast.LENGTH_SHORT).show(); } } } private void swapImageAdapter(){ Log.i(TAG,"swapImageAdapter"+mImageFolder.toString()+"mGalleryFolder from MainActivity!!"); RecyclerView.Adapter newImageAdapter=new ImageAdapter(mImageFolder); mRecycleView.swapAdapter(newImageAdapter,false); } private File[] sortFilesToLatest(File fileImagesDir) { File[] files = fileImagesDir.listFiles(); Arrays.sort(files, new Comparator<File>() { @Override public int compare(File lhs, File rhs) { return Long.valueOf(rhs.lastModified()).compareTo(lhs.lastModified()); } }); return files; } }
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0,90); ORIENTATIONS.append(Surface.ROTATION_90,0); ORIENTATIONS.append(Surface.ROTATION_180,270); ORIENTATIONS.append(Surface.ROTATION_270,180); } private static final String TAG = "MainActivity"; private static final int STATE_PREVIEW=0; private static final int STATE_WAIT_AF_LOCK=1; private static final int STATE_PICTURE_CAPTURED=2; private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0; private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT = 1; private static final int REQUEST_READ_EXTERNAL_STORAGE_REQUEST = 2; private int mState; private static LruCache<String, Bitmap> mMemoryCache; private HandlerThread mBackgroundThread; private final Handler mUIHandler = new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg){ swapImageAdapter(); } }; private static File mImageFile; private Handler mBackgroundHandler; private TextureView mTextureView; private Button mCaptureButton; private File mImageFolder; private static String mImageFileName; private Size mPreviewSize; //mImageSize private RecyclerView mRecycleView; private String mCameraId; private CameraDevice mCameraDevice; private CaptureRequest mPreviewCaptureRequest; private CaptureRequest.Builder mPreviewCaptureRequestBuilder; private CameraCaptureSession mCameraCaptureSession; private ImageReader mImageReader; private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener(){ @Override public void onImageAvailable(ImageReader reader){ Log.i(TAG,"OnImageAvailableListener!!!"); mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(),mUIHandler)); } }; private static class ImageSaver implements Runnable{ private final Image mImage; private final Handler mHandler; ImageSaver(Image image){ Log.i(TAG,"imgSaver const"); mImage=image; mHandler=null; } ImageSaver(Image image,Handler handler){ Log.i(TAG,"imgSaver const"); mImage =image; mHandler =handler; } @Override public void run(){ Log.i(TAG,"In ImageSaver run()"); ByteBuffer byteBuffer=mImage.getPlanes()[0].getBuffer(); byteBuffer.rewind(); byte[] bytes = new byte[byteBuffer.capacity()]; byteBuffer.get(bytes); FileOutputStream fileOutputStream = null; try{ fileOutputStream =new FileOutputStream(mImageFileName); fileOutputStream.write(bytes); }catch(IOException e){ e.printStackTrace(); } finally{ Log.i(TAG,"Closing Image!!"); mImage.close(); if(fileOutputStream!=null){ try { fileOutputStream.close(); }catch(IOException e){ e.printStackTrace(); } } } Message message = mHandler.obtainMessage(); Log.i(TAG,"sending Message from Image Saver run()"); message.sendToTarget(); } } private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); Log.i(TAG,"mSessionCaptureCallback+ onCaptureStarted"); } @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result){ super.onCaptureCompleted(session,request,result); Log.i(TAG,"mSessionCaptureCallback+ onCaptureCompleted"); process(result); //process the result once capture session request is completed. Log.i(TAG,"mSessionCaptureCallback+ onCaptureCompleted ENDS!"); } @Override public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure){ super.onCaptureFailed(session, request, failure); Toast.makeText(getApplicationContext(),"Focus Lock UnSucessfull!", Toast.LENGTH_SHORT).show(); } private void process(CaptureResult result){ Log.i(TAG,"mSTATE_PICTURE_CAPTURED"+mState); switch (mState){ case STATE_PREVIEW: break; case STATE_WAIT_AF_LOCK: Log.i(TAG,"process_ wait_AF_LOCK"); Integer afState=result.get(CaptureResult.CONTROL_AF_STATE); if(afState==CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED){ Log.i(TAG,"Lock Sucessfull!"); Toast.makeText(getApplicationContext(),"Lock Sucessfull!", Toast.LENGTH_SHORT).show(); mState=STATE_PICTURE_CAPTURED; captureStillImage(); } Log.i(TAG,"Out of process_WAIT_AF_LOCK"); break; case STATE_PICTURE_CAPTURED: break; } } }; private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice cameraDevice) { Log.i(TAG,"CameraDeviceStateCallback+ onOpened"); mCameraDevice = cameraDevice; Toast.makeText(getApplicationContext(), "Cam Opened!", Toast.LENGTH_SHORT).show(); createCameraPreviewSession(); } @Override public void onClosed(CameraDevice dev){ mCameraDevice=null; } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { Log.i(TAG,"CameraDeviceStateCallback+ onDisconnected"); cameraDevice.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice cameraDevice, int error) { cameraDevice.close(); mCameraDevice = null; Log.i(TAG, "Error Number:" + error + "While opening camera!!!"); } }; private TextureView.SurfaceTextureListener mSurfaceTexture = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { Log.i(TAG, "SurfaceTexture Available"); setupCamera(width, height); Log.i(TAG, "in onSurfaceTextureAvailable "); transformImage(width, height); Log.i(TAG, "in onSurfaceTextureAvailable "); openCamera(); Log.i(TAG, "in onSurfaceTextureAvailable "); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { Log.i(TAG, "in onSurfaceTextureSizeChanged "); } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { Log.i(TAG, "in onSurfaceTextureTextureUpdated"); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.i(TAG, "SurfaceTexture Destroyed"); return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); createImageFolder(); setContentView(R.layout.activity_main); if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED) { mRecycleView = (RecyclerView) findViewById(R.id.galleryRecyclerView); GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 1); mRecycleView.setLayoutManager(gridLayoutManager); RecyclerView.Adapter imageAdapter = new ImageAdapter(mImageFolder); Log.i(TAG, "RecyclerViewSetup!"); mTextureView = (TextureView) findViewById(R.id.textureView); Log.i(TAG, "TextureViewSetup!"); mCaptureButton = (Button) findViewById(R.id.captureButton); mCaptureButton.setOnClickListener(this); } else{ if(shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_READ_EXTERNAL_STORAGE_REQUEST); } } Log.i(TAG,"onCreate Completed"); } @Override public void onResume() { super.onResume(); openBackgroundThread(); if (mTextureView.isAvailable()) { setupCamera(mTextureView.getWidth(), mTextureView.getHeight()); transformImage(mTextureView.getWidth(),mTextureView.getHeight()); if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { openCamera(); } else { if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { Toast.makeText(this, "App needs to be able to save Images", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT); } } else { mTextureView.setSurfaceTextureListener(mSurfaceTexture); } } @Override public void onPause() { closeCamera(); closeBackgroundThread(); super.onPause(); } public void setupCamera(int width, int height) { Log.i(TAG,"setupcam"); CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { for (String cameraId : cameraManager.getCameraIdList()) { CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { continue; } StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size largestImageSize = Collections.max( Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() { @Override public int compare(Size size, Size t1) { return Long.signum(size.getWidth()*size.getHeight()- t1.getWidth()*t1.getHeight()); } } ); mImageReader = ImageReader.newInstance(largestImageSize.getWidth(),largestImageSize.getHeight(),ImageFormat.JPEG,1); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener,mBackgroundHandler); mPreviewSize = getPrefferedPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height); mCameraId = cameraId; Log.i(TAG,"Setup Camera Ends!!"); return; } } catch (CameraAccessException e) { e.printStackTrace(); } } private Size getPrefferedPreviewSize(Size[] mapSizes, int width, int height) { List<Size> collectorSizes = new ArrayList<>(); for (Size size : mapSizes) { if (width > height) { if (size.getWidth() > width && size.getHeight() > height) { collectorSizes.add(size); } else { if (size.getWidth() > height && size.getHeight() > width) { collectorSizes.add(size); } } } } if (collectorSizes.size() > 0) { return Collections.min(collectorSizes, new Comparator<Size>() { @Override public int compare(Size lhs, Size rhs) { return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth()); } }); } return mapSizes[0]; } public void openCamera() { Log.i(TAG,"In OpenCamera"); CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE); try { Log.i(TAG,"CamaeraManager.OpenCamera"); cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); Log.i(TAG,"CamaeraManager.OpenCameraEnds"); } catch(SecurityException s){ s.printStackTrace(); } catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"OpenCamera Ends"); } public void closeCamera(){ if(mImageReader!=null){ mImageReader.close(); mImageReader=null; } if(mCameraCaptureSession!=null) { mCameraCaptureSession.close(); mCameraCaptureSession = null; } if(mCameraDevice!=null){ mCameraDevice.close(); mCameraDevice = null; } } public void createCameraPreviewSession(){ try{ Log.i(TAG,"CREATE_PREVIEW_CAMERA_SESSION"); SurfaceTexture surfaceTexture=mTextureView.getSurfaceTexture(); surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight()); Surface previewSurface = new Surface(surfaceTexture); mPreviewCaptureRequestBuilder=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewCaptureRequestBuilder.addTarget(previewSurface); mCameraDevice.createCaptureSession( Arrays.asList(previewSurface,mImageReader.getSurface()), new CameraCaptureSession.StateCallback(){ @Override public void onConfigured(CameraCaptureSession session){ Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigured"); if(null == mCameraDevice){ return; } try{ mPreviewCaptureRequest=mPreviewCaptureRequestBuilder.build(); mCameraCaptureSession = session; mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequest,mSessionCaptureCallback,mBackgroundHandler); } catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigured setRepeatingRequests"); } @Override public void onConfigureFailed(CameraCaptureSession session){ Log.i(TAG,"mCameraDevice.careateCaptireSession onConfigurationFailed"); Toast.makeText(getApplicationContext(),"CreateCameraSession FAILED!!",Toast.LENGTH_SHORT).show(); } } ,null); }catch(CameraAccessException e){ e.printStackTrace(); } } private void clickPic(){ Log.i(TAG,"in ClickPic"); lockFocus(); Log.i(TAG,"exiting ClickPic"); } private void lockFocus(){ try { Log.i(TAG,"lockFocus"); mState = STATE_WAIT_AF_LOCK; mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,CaptureRequest.CONTROL_AF_TRIGGER_START); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(), mSessionCaptureCallback, mBackgroundHandler); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"exiting lockFocus"); } private void unlockFocus(){ try { Log.i(TAG,"unlockFocus"); mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),mSessionCaptureCallback,mBackgroundHandler); mState = STATE_PREVIEW; mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequestBuilder.build(), mSessionCaptureCallback, mBackgroundHandler); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"exiting lockFocus"); } private void openBackgroundThread(){ mBackgroundThread=new HandlerThread("Camera Background Thread"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { public void handleMessage(Message msg) { Log.i(TAG,"Inside Background Handler"); } }; } private void closeBackgroundThread(){ Log.i(TAG,"closing Background Thread!"); mBackgroundThread.quitSafely(); try{ mBackgroundThread.join(); mBackgroundThread = null; mBackgroundHandler = null; }catch(InterruptedException e){ e.printStackTrace(); } } private void captureStillImage(){ try { Log.i(TAG,"captureStillImage"); mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); mPreviewCaptureRequestBuilder.addTarget(mImageReader.getSurface()); int rotation = getWindowManager().getDefaultDisplay().getRotation(); mPreviewCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation)); CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback(){ @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result){ Log.i(TAG,"captureStillImage+ onCaptureCompleted"+mImageFileName); Toast.makeText(getApplicationContext(),"Image Captured!",Toast.LENGTH_SHORT).show(); unlockFocus(); } public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); Log.i(TAG,"captureStillImage+ onCapturestarted"); try { mImageFile=createImageFileName(); } catch (IOException e) { e.printStackTrace(); } } }; CameraCaptureSession.stopRepeating(); mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),captureCallback,null); }catch(CameraAccessException e){ e.printStackTrace(); } Log.i(TAG,"captureStillImage Ends!"); } private void transformImage(int width,int height){ Matrix matrix = new Matrix(); if(mPreviewSize==null||mTextureView==null) { return; } int rotation = getWindowManager().getDefaultDisplay().getRotation(); RectF textureRectF = new RectF(0,0,width,height); RectF previewRectF = new RectF(0,0,mPreviewSize.getHeight(),mPreviewSize.getWidth()); float centerX = textureRectF.centerX(); float centerY = textureRectF.centerY(); if(rotation==Surface.ROTATION_90||rotation==Surface.ROTATION_270){ previewRectF.offset(centerX - previewRectF.centerX(),centerY-previewRectF.centerY()); matrix.setRectToRect(textureRectF,previewRectF,Matrix.ScaleToFit.FILL); float scale = Math.max((float)width/mPreviewSize.getWidth(), (float)height/mPreviewSize.getHeight()); matrix.postScale(scale,scale,centerX,centerY); matrix.postRotate(90*(rotation-2),centerX,centerY); } mTextureView.setTransform(matrix); } @Override public void onClick(View view){ switch(view.getId()){ case R.id.captureButton: clickPic(); break; } } private void checkPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { try { createImageFileName(); } catch (IOException e) { e.printStackTrace(); } } else { if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, "App needs to be able to save Images", Toast.LENGTH_SHORT).show(); } requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT); } } private void createImageFolder() { Log.i(TAG,"createImageFolder"); File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); mImageFolder = new File(imageFile, "camera2Api"); if(!mImageFolder.exists()) { mImageFolder.mkdirs(); } } private File createImageFileName() throws IOException { Log.i(TAG,"createImageFileName"); String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String prepend = "IMG_" + timestamp + "_"; File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder); mImageFileName = imageFile.getAbsolutePath(); Log.i(TAG,"Image FILE NAME="+mImageFileName); return imageFile; } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) { if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "Application will not run without camera services", Toast.LENGTH_SHORT).show(); } } if(requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Permission successfully granted!", Toast.LENGTH_SHORT).show(); } } if(requestCode==REQUEST_READ_EXTERNAL_STORAGE_REQUEST){ if(grantResults[0]==PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "Permission successfully granted!", Toast.LENGTH_SHORT).show(); } } } private void swapImageAdapter(){ Log.i(TAG,"swapImageAdapter"+mImageFolder.toString()+"mGalleryFolder from MainActivity!!"); RecyclerView.Adapter newImageAdapter=new ImageAdapter(mImageFolder); mRecycleView.swapAdapter(newImageAdapter,false); } private File[] sortFilesToLatest(File fileImagesDir) { File[] files = fileImagesDir.listFiles(); Arrays.sort(files, new Comparator<File>() { @Override public int compare(File lhs, File rhs) { return Long.valueOf(rhs.lastModified()).compareTo(lhs.lastModified()); } }); return files; } }
这是用于在RecyclerView中对ImageView进行充气的ImageAdapter类: -
public class ImageAdapter extends RecyclerView.Adapter {
private static final String TAG="ImageAdapter";
private File imagesFile;
public ImageAdapter(File folderFile) {
Log.i(TAG,folderFile.toString()+"printing Folder File FROM IMAGE_ADAPTER!!!!");
imagesFile = folderFile;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i(TAG,"onCreateViewHolder");
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.activity_image, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.i(TAG,"onBindViewHolder");
BitmapFactory.Options mBitOptions = new BitmapFactory.Options();
mBitOptions.inScaled=true;
mBitOptions.inSampleSize=2;
int size = imagesFile.listFiles().length;
Log.i(TAG,imagesFile.toString()+" its SIZE="+size+" position="+position);
Log.i(TAG,"CONSIDERING FILE:"+imagesFile.listFiles()[position].getPath());
File imageFile = imagesFile.listFiles()[position];
Bitmap imageBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath(),mBitOptions);
holder.getImageView().setImageBitmap(imageBitmap);
}
@Override
public int getItemCount() {
Log.i(TAG,"getItemCount");
return imagesFile.listFiles().length;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
public ViewHolder(View view) {
super(view);
imageView = (ImageView) view.findViewById(R.id.imageGalleryView);
}
public ImageView getImageView() {
return imageView;
}
}
}
Activity_image.xml在RelativeLayout中包含ImageView。由于字符限制,我无法提供代码。 请告诉我我做错了什么?