How get barcode row value from camera preview in TextureView? - android

I'm noob in android.
Can anybody help to anderstanding google ml-kit barcodereader?
I create activity with TextureView.
Camera live-preview in TextureView.
In activity code i create scanBarcode(Bitmap bitmap) method.
But I can't get barcode value.(((
I use this tutorial to Create scanBarcode method.
https://firebase.google.com/docs/ml-kit/android/read-barcodes
What i do wrong?
public class BarcodeScannerActivityNew extends AppCompatActivity {
private TextureView textureView; //элемент где будет превью
private String cameraId; //id камеры, с которой будем забирать изображение
private Size imageDimension; // размер изображения с камеры
private static final int REQUEST_CAMERA_PERMISSION = 200; //200 - разрешение есть
protected CameraDevice cameraDevice; // камера для колбэка
protected CaptureRequest.Builder captureRequestBuilder; // создание запроса к camera2
protected CameraCaptureSession cameraCaptureSessions;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private String bcTitle;
private TextView txt;
//private FirebaseVisionImage fbImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode_scanner_new);
textureView = (TextureView) findViewById(R.id.texture);
textureView.setSurfaceTextureListener(textureListener);
txt = (TextView) findViewById(R.id.editText);
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera(); //открываем камеру
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Изменяем размер превью по элементу TextureView
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// сюда бабахнуть сканнер??
}
};
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0]; // первая камера
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// Проверяем есть ли разрешения для камеры, если нет запрашиваем
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(BarcodeScannerActivityNew.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null); //колбэк камеры
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//Когда камера открыта
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
final Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//Камера закрыта
if (null == cameraDevice) {
return;
}
// Когда сессия готова показываем.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(BarcodeScannerActivityNew.this, "Настройки изменились", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void updatePreview() {
if(null == cameraDevice) {
//вывод ошибки обновления превью
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
Bitmap bitmapi = textureView.getBitmap();
if(bitmapi!=null){
scanBarcode(bitmapi);
}
if(bcTitle != null){
txt.setText(bcTitle);
}
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// Закрыть приложение
Toast.makeText(BarcodeScannerActivityNew.this, "Без разрешения камеры невозможно использовать приложение", Toast.LENGTH_LONG).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void onPause() {
//closeCamera();
stopBackgroundThread();
super.onPause();
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void scanBarcode(Bitmap bitmap){
FirebaseVisionBarcodeDetectorOptions options =
new FirebaseVisionBarcodeDetectorOptions.Builder()
.setBarcodeFormats(
FirebaseVisionBarcode.FORMAT_EAN_13)
.build();
//bcTitle="куку";
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance()
.getVisionBarcodeDetector(options);
//bcTitle="куку";
Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)
.addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>() {
#Override
public void onSuccess(List<FirebaseVisionBarcode> barcodes) {
// Task completed successfully
// ...
//bcTitle="aaa";//сюда попадаем после разблокировки экрана, возможно перперисовать интерфейс, даже если ничего не поймал
for (FirebaseVisionBarcode barcode: barcodes) {
bcTitle="aaa";
Rect bounds = barcode.getBoundingBox();
Point[] corners = barcode.getCornerPoints();
String rawValue = barcode.getRawValue();
int valueType = barcode.getValueType();
bcTitle = barcode.getRawValue();
// See API reference for complete list of supported types
/*
switch (valueType) {
case FirebaseVisionBarcode.TYPE_WIFI:
String ssid = barcode.getWifi().getSsid();
String password = barcode.getWifi().getPassword();
int type = barcode.getWifi().getEncryptionType();
break;
case FirebaseVisionBarcode.TYPE_URL:
String title = barcode.getUrl().getTitle();
String url = barcode.getUrl().getUrl();
break;
}
*/
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
// ...
bcTitle="ffff";
}
});
}
}

Related

Android textureView stretched

SurfaceTexture preview is stretched! I'm developing a camera2 app. Every device is working bad. The preview for video and photo is stretched.
public class CamActivity extends AppCompatActivity {
private static final int REQUEST_LOCATION = 1;
LocationManager locationManager;
Animation animFadeOut, textAnimFadeOut;
ImageView viewFadeOut;
TextView textFadeOut, Lado;
private TextureView textureView;
private FloatingActionButton btnCapture;
//Check state orientation of output image
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0,0);
}
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
//Save to FILE
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cam);
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
Lado = (TextView)findViewById(R.id.lado_armadilha);
Lado.setText(getIntent().getStringExtra("lado_armadilha"));
viewFadeOut = (ImageView)findViewById(R.id.viewFadeOut);
animFadeOut = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fade);
viewFadeOut.startAnimation(animFadeOut);
textFadeOut =(TextView)findViewById(R.id.textFadeOut);
textAnimFadeOut = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_text);
textFadeOut.startAnimation(textAnimFadeOut);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (FloatingActionButton) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == null)
return;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
Log.i("JPEG_SIZE", "" + jpegSizes[0].getWidth());
Log.i("JPEG_SIZE", "" + jpegSizes[0].getHeight());
//Capture image with custom size
int width = jpegSizes[0].getWidth();
int height =jpegSizes[0].getHeight();
if(jpegSizes == null && jpegSizes.length < 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(getIntent().getStringExtra(MediaStore.EXTRA_OUTPUT));
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireNextImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
Log.e("ioexception", e.getMessage());
}
finally {
if(image != null)
image.close();
}
Intent intent = new Intent();
intent.putExtra("Bitmap",file.getAbsolutePath());
setResult(1,intent);
finish();
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CamActivity.this, "Saved "+file, Toast.LENGTH_SHORT).show();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try {
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if (cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(CamActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread= null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
}
A TextureView will by default just stretch whatever images you give it into its view dimensions. So if you give it a 1920x1080 buffer (16:9 aspect ratio) but its dimensions are 1600x1200 (4:3), you'll get a vertically squished image shown.
Take a look at the AutoFitTextureView in the Camera2Basic sample from Google.
It tries to ensure that its aspect ratio matches that of the camera, but it does require you to set its layout parameters correctly (and it has to be in a layout container that allows its children some flexibility in sizing).

How to do Real time Image Processing from crop Image in Android studio

I am doing some work on Android Studio with minSdkVersion 21 and targetSdkVersion 28.
The program performs a photopletysmography which, through the use of
the anterior camera, detects in real time a signal proportional to the absorption of light in the face and extracts the respiratory activity.
My Idea is: place the face inside the black rectangle and study only part of image inside it.
rectangle.xml res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/transparent"/>
<corners android:radius="12px"/>
<stroke android:width="2dip" android:color="#000000"/>
</shape>
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="edmt.dev.androidcamera2api.MainActivity">
<TextureView
android:id="#+id/textureView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/btnCapture"
/>
<Button
android:id="#+id/btnCapture"
android:text="CAPTURE"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/rectimage"
android:layout_width="196dp"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="145dp"
android:src="#drawable/rectangle"></ImageView>
</RelativeLayout>
MainActivity.java:
package edmt.dev.androidcamera2api;
import [...]
public class MainActivity extends AppCompatActivity {
private Button btnCapture;
private TextureView textureView;
//Check state orientation of output image
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 String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
//Save to FILE
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (Button)findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == null)
return;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
//Capture image with custom size
int width = 640;
int height = 480;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory()+"/"+UUID.randomUUID().toString()+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved "+file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try{
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread= null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
}
edit how to create a "invisible" layer instead of a rectangle and use it to study an Image?

How to handle camera flash android camera2 API?

I want to set flash off,on and auto as user selection. How should I do that?
In this code if I enable flash it is on but when I click image flash goes off. And when I change camera at that time also flash goes off.
If the user sets flash to enable then when the user clicks an image only at that time flash should go on and after that it should be off.
public class MainActivity extends AppCompatActivity {
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest.Builder captureRequestBuilder;
private boolean deviceHasFlash;
private boolean flashStatus=false;
private String cameraId=CAMERA_BACK;
private Size imageDimension;
private ImageReader imageReader;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private static final int PERMISSION_CODE = 200;
public static final String CAMERA_FRONT = "1";
public static final String CAMERA_BACK = "0";
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);
}
ImageView captureImage;
ImageView flash;
ImageView switchCamera;
private TextureView textureView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
captureImage = findViewById(R.id.btn_camera_shutter);
textureView = (TextureView) findViewById(R.id.textureView);
flash=findViewById(R.id.btn_flash);
switchCamera=findViewById(R.id.btn_camera_switch);
if (checkPermission()) {
setCameraView();
createFolderIfNotExists();
Log.e("DB", "Permission is Given");
} else {
Log.e("DB", "Ask For Permission");
requestPermission();
}
captureImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
takePicture();
}
});
switchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switchCameraFunction();
}
});
flash.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
deviceHasFlash = getApplication().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if(!deviceHasFlash){
Toast.makeText(MainActivity.this, "Sorry, you device does not have any camera", Toast.LENGTH_LONG).show();
}
else {
if(flashStatus){
flashOff();
flash.setImageResource(R.drawable.ic_flash_off);
flashStatus=false;
}
else {
flashOn();
flash.setImageResource(R.drawable.ic_flash_on);
flashStatus=true;
}
}
}
});
}
private void switchCameraFunction() {
if (cameraId.equals(CAMERA_FRONT)) {
cameraId = CAMERA_BACK;
closeCamera();
reopenCamera();
} else if (cameraId.equals(CAMERA_BACK)) {
cameraId = CAMERA_FRONT;
closeCamera();
reopenCamera();
}
}
private void reopenCamera() {
if (textureView.isAvailable()) {
Log.e("DB", "reopenCamera if");
openCamera();
} else {
Log.e("DB", "reopenCamera else");
textureView.setSurfaceTextureListener(textureListener);
}
}
private void flashOff() {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void flashOn() {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void setCameraView() {
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
}
private void createFolderIfNotExists() {
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "CrazyCam");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
if (success) {
Log.e("DB", "Folder Created");
} else {
Log.e("DB", "Something Wrong");
}
} else {
Log.e("DB", "Folder exists");
}
}
private boolean checkPermission() {
int readExternal = ContextCompat.checkSelfPermission(getApplicationContext(), READ_EXTERNAL_STORAGE);
int writeExternal = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
int camera = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
return camera == PackageManager.PERMISSION_GRANTED && writeExternal == PackageManager.PERMISSION_GRANTED && readExternal == PackageManager.PERMISSION_GRANTED;
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE, CAMERA, READ_EXTERNAL_STORAGE}, PERMISSION_CODE);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_CODE:
if (grantResults.length > 0) {
boolean wrireExteernal = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
boolean readExternal = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (wrireExteernal && cameraAccepted && readExternal) {
setCameraView();
createFolderIfNotExists();
Log.e("DB", "Permission is Given");
} else {
Toast.makeText(getApplicationContext(), "All Permission Requeid", Toast.LENGTH_LONG).show();
System.exit(0);
}
}
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e("DB", "is camera open");
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
Log.e("DB","imageDimension===>"+imageDimension);
// Add permission for camera and let user grant the permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_CODE);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e("DB", "openCamera X");
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
Log.e("DB","onSurfaceTextureAvailable");
}
#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 final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//This is called when the camera is open
Log.e("DB", "onOpened");
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice = null;
}
};
/* #Override
protected void onDestroy() {
closeCamera();
Log.e("DB","On Destroy Call");
super.onDestroy();
}
*/
private void closeCamera() {
if (null != cameraDevice) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
}
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
Log.e("DB", "onResume");
startBackgroundThread();
if (textureView.isAvailable()) {
Log.e("DB", "textureView if");
openCamera();
} else {
Log.e("DB", "textureView else");
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
Log.e("DB", "onPause");
closeCamera();
stopBackgroundThread();
super.onPause();
}
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void updatePreview() {
if(null == cameraDevice) {
Log.e("DB", "updatePreview error, return");
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void takePicture() {
if(null == cameraDevice) {
Log.e("DB", "cameraDevice is null");
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
Size[] jpegSizes = null;
if (characteristics != null) {
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
}
int width = 640;
int height = 480;
for(int i=0;i<jpegSizes.length;i++){
Log.e("DB==>","Size:"+jpegSizes[i]);
}
if (jpegSizes != null && 0 < jpegSizes.length) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
final File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "CrazyCam");
String fileName = String.format("CrazyCam_" + System.currentTimeMillis() + ".jpg");
final File outFile = new File(folder, fileName);
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(outFile);
outStream.write(bytes);
outStream.flush();
} finally {
if (null != outStream) {
outStream.close();
}
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(getApplicationContext(), "Image Save at " + folder, Toast.LENGTH_LONG).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}

Real time zoom in Camera2

I am a bit of a newbie and trying to build an app based on https://inducesmile.com/android/android-camera2-api-example-tutorial/ to assist a hard of sight individual. I need to use a Bluetooth game controller to control the zoom level in real time- when a button is pressed, the zoom level changes. I have removed the "Take Picture" button and top banner so that I can use full screen. I have tried to change the zoom level in different methods: createCameraPreview, updatePreview and dispatchKeyEvent but its not working. Where should I apply the new captureRequestBuilder with the updated zoom Rect? Thanks.
+import ...
public class AndroidCameraApi extends AppCompatActivity {
private static final String TAG = "AndroidCameraApi";
private TextureView textureView;
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 String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest captureRequest;
protected CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private int kc; //kc is keyCode from bluetooth controller
Rect zoomCropPreview = new Rect(1094, 822, 2186, 1642); //zoomed in
//Rect zoomCropPreview = new Rect(0,0,4032,3024); //full screen
#Override
protected void onCreate(Bundle savedInstanceState) { //onCreate set up layout, texture, take pciture button
super.onCreate(savedInstanceState);
//this.requestWindowFeature(Window.FEATURE_NO_TITLE); //remove title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //remove notification mar
setContentView(R.layout.activity_android_camera_api);
textureView = (TextureView) findViewById(R.id.texture); //set up texture
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//open your camera here
openCamera();
}
};
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
Float maxDigitalZoom = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); //get maximum digital zoom (=8)
Rect asd = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// Add permission for camera and let user grant the permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(AndroidCameraApi.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//This is called when the camera is open
Log.e(TAG, "onOpened");
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
//try to change zoom- didn't work
//captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
//try to change zoom here- didn't work
//captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
cameraCaptureSessions = cameraCaptureSession;
updatePreview(); //update preview screen
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(AndroidCameraApi.this, "Configuration change", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void updatePreview() {
if (null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
}
// Original
//captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Modified
captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
//********************************
// Change zoom based on Bluetooth controller
//********************************
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
kc = event.getKeyCode();
Log.i("key pressed", String.valueOf(kc));
//as a test, just change from zoomed in to full screen
zoomCropPreview.set(0,0,4032,3024); //change to full screen
Log.i("zoomCropPreview", (zoomCropPreview).flattenToString());
//try to change zoom- didn't work
captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
return super.dispatchKeyEvent(event);
}
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(AndroidCameraApi.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if (null != cameraDevice) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// close the app
Toast.makeText(AndroidCameraApi.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
Log.e(TAG, "onPause");
//closeCamera();
stopBackgroundThread();
super.onPause();
}
}
You need to call cameraCaptureSessions.setRepeatingRequest again after you've updated all the settings in captureRequestBuilder.
Just updating the builder does nothing on its own, it's just modifying a bundle of settings. You need to tell the camera to actually use the new bundle for anything to happen.

Lacking privileges to access camera service in Android 6.0

I am using Camera2API in Android 6.0. I was done without error in Android 5.0. However, when I used my code in the Android 6.0, I have a issue. The issue is that sometime I can open the camera successfully and take picture. However, sometime the camera cannot open and it has error
java.lang.SecurityException: Lacking privileges to access camera service
at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
I added the runtime permission as follows:
String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!hasAllPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
}
public static boolean hasAllPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
This is all log
FATAL EXCEPTION: main
Process: com.example.camera2api, PID: 5376
java.lang.SecurityException: Lacking privileges to access camera service
at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
at android.hardware.camera2.utils.CameraBinderDecorator$CameraBinderDecoratorListener.onAfterInvocation(CameraBinderDecorator.java:73)
at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81)
at java.lang.reflect.Proxy.invoke(Proxy.java:393)
at $Proxy2.cancelRequest(Unknown Source)
at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:926)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:378)
at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected(CameraCaptureSessionImpl.java:514)
at android.hardware.camera2.impl.CameraDeviceImpl$7.run(CameraDeviceImpl.java:228)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
update: For someone who want to look at my full code. I upload my full code here
public class AndroidCamera extends AppCompatActivity {
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 = "Camera2App";
private String mImageFileLocation = "";
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAIT_LOCK = 1;
private static final int STATE_WAITING_PRECAPTURE = 2;
/**
* Camera state: Waiting for the exposure state to be something other than precapture.
*/
private static final int STATE_WAITING_NON_PRECAPTURE = 3;
/**
* Camera state: Picture was taken.
*/
private static final int STATE_PICTURE_TAKEN = 4;
private int mState;
private TextureView mTextureView;
private Size mPreviewSize;
private String mCameraId;
String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA};
private static final int PERMISSION_ALL = 105;
private static final int REQUEST_CAMERA_RESULT = 106;
private boolean isRegistred=false;
private int mSensorOrientation;
private TextureView.SurfaceTextureListener mSurfaceTextureListener =
new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
setupCamera(width, height,BleUtils.getCameraLens(AndroidCamera.this));
else
setupCamera(width, height,"1");
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
//closeCamera();
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback =
new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
mCameraOpenCloseLock.release();
mCameraDevice = camera;
//Toast.makeText(getApplicationContext(),"Camera Opened!", Toast.LENGTH_SHORT).show();
createCameraPreviewSession();
}
#Override
public void onDisconnected(CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
#Override
public void onError(CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
private CaptureRequest mPreviewCaptureRequest;
private CaptureRequest.Builder mPreviewCaptureRequestBuilder;
private CameraCaptureSession mCameraCaptureSession;
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result){
switch (mState){
case STATE_PREVIEW:
break;
case STATE_WAIT_LOCK:
Integer afState=result.get(CaptureResult.CONTROL_AF_STATE);
if(afState==CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED){
captureStillImage();
}
else{
captureStillImage();
}
break;
}
}
#Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
process(result);
}
#Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
super.onCaptureFailed(session, request, failure);
Handler mHandler = new Handler(getMainLooper());
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Focus Lock UnSuccesful", Toast.LENGTH_SHORT).show();
}
});
}
};
private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private static File mImageFile;
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage()));
}
};
private static class ImageSaver implements Runnable {
private final Image mImage;
private ImageSaver(Image image) {
mImage = image;
}
#Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFile);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_activity);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!hasAllPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
}
mTextureView = (TextureView) findViewById(R.id.texture);
}
public static boolean hasAllPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
#Override
public void onStart() {
super.onStart();
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
}
//onStop
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
#Subscribe
public void onCaptureNumberReceived(OnCaptureEvent event) {
//get the phone number value here and do something with it
String capturecode = event.getCodeCapture();
Log.d(TAG, capturecode);
if (capturecode.equals("capture")) {
try {
mImageFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
lockFocus();
MediaActionSound sound = new MediaActionSound();
sound.play(MediaActionSound.SHUTTER_CLICK);
}
else if(capturecode.equals("end_capture")) {
finish(); // call this to finish the current activity
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory( Intent.CATEGORY_HOME );
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
}
}
public void takepicture(View view) {
try {
mImageFile = createImageFile();
Log.d("TAG","=====Take picture=====");
} catch (IOException e) {
e.printStackTrace();
}
lockFocus();
MediaActionSound sound = new MediaActionSound();
sound.play(MediaActionSound.SHUTTER_CLICK);
}
public void switch_camera(View view) {
closeCamera();
//swap the id of the camera to be used
if(mCameraId == String.valueOf(Camera.CameraInfo.CAMERA_FACING_BACK)){
mCameraId = String.valueOf(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
else {
mCameraId = String.valueOf(Camera.CameraInfo.CAMERA_FACING_BACK);
}
BleUtils.setCameraLens(this, mCameraId);
if (mTextureView.isAvailable()) {
setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),mCameraId);
openCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "BLE_" + timeStamp + "_";
File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if(!storageDirectory.exists()){
if(!storageDirectory.mkdirs()){
Log.e("Dir", "Failed to create directory");
Log.d("MAKE DIR", storageDirectory.mkdir() + "" + storageDirectory.getParentFile() + "");
return null;
}
}
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
mImageFileLocation = image.getAbsolutePath();
return image;
}
#Override
public void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!hasAllPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
}
openBackgroundThread();
if (mTextureView.isAvailable()) {
if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),BleUtils.getCameraLens(AndroidCamera.this));
else
setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),"1");
closeCamera();
openCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy");
}
public void onPause() {
Log.d(TAG,"onPause");
closeCamera();
closeBackgroundThread();
super.onPause();
}
private void setupCamera(int width, int height, String cameraId) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
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 lhs, Size rhs) {
return Long.signum(lhs.getWidth() * lhs.getHeight() -
rhs.getWidth() * rhs.getHeight());
}
}
);
mImageReader = ImageReader.newInstance(largestImageSize.getWidth(),
largestImageSize.getHeight(),
ImageFormat.JPEG,
1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener,
mBackgroundHandler);
mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
mCameraId = cameraId;
Log.d("CAMERA_ID",String.valueOf(mCameraId));
// }
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) {
List<Size> collectorSizes = new ArrayList<>();
for (Size option : mapSizes) {
if (width > height) {
if (option.getWidth() > width &&
option.getHeight() > height) {
collectorSizes.add(option);
}
} else {
if (option.getWidth() > height &&
option.getHeight() > width) {
collectorSizes.add(option);
}
}
}
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.getWidth() * rhs.getHeight());
}
});
}
return mapSizes[0];
}
private void openCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
Log.v("CAMERA", mCameraId + " " + mCameraDeviceStateCallback);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED){
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback,mBackgroundHandler);
}
else {
if (shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)){
Toast.makeText(this,"No Permission to use the Camera services", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[] {android.Manifest.permission.CAMERA},REQUEST_CAMERA_RESULT);
}
}
else {
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode){
case REQUEST_CAMERA_RESULT:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "Cannot run application because camera service permission have not been granted", Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
private void closeCamera(){
if(mCameraCaptureSession!=null){
mCameraCaptureSession.close();
mCameraCaptureSession=null;
}
if (mCameraDevice!=null){
mCameraDevice.close();
mCameraDevice=null;
if(mImageReader!=null){
mImageReader.close();
mImageReader=null;
}
}
}
private void createCameraPreviewSession(){
try{
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
Surface previewSurface= new Surface(surfaceTexture);
mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewCaptureRequestBuilder.addTarget(previewSurface);
mPreviewCaptureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte)100);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
if(mCameraDevice==null){
return;
}
try {
mPreviewCaptureRequest = mPreviewCaptureRequestBuilder.build();
mCameraCaptureSession = session;
mCameraCaptureSession.setRepeatingRequest(
mPreviewCaptureRequest,
mSessionCaptureCallback,
mBackgroundHandler
);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Handler mHandler = new Handler(getMainLooper());
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(
getApplicationContext(),
"create camera session failed!",
Toast.LENGTH_SHORT
).show();
}
});
}
},null);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private void openBackgroundThread(){
mBackgroundThread=new HandlerThread("Camera2 background thread");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
private void closeBackgroundThread(){
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread=null;
mBackgroundHandler=null;
}catch (InterruptedException e){
e.printStackTrace();
}
}
private void lockFocus(){
try{
mState=STATE_WAIT_LOCK;
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START);
mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
mSessionCaptureCallback,mBackgroundHandler);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private void unLockFocus(){
try{
mState=STATE_PREVIEW;
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
mSessionCaptureCallback,mBackgroundHandler);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private void captureStillImage(){
try {
CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureStillBuilder.addTarget(mImageReader.getSurface());
// Use the same AE and AF modes as the preview.
captureStillBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// setAutoFlash(captureBuilder);
// Orientation
int rotation=0;
//Front camera
if(mCameraId.equals("1")) {
rotation = this.getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
}
else {
rotation = this.getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
}
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
//Toast.makeText(getApplicationContext(),"Image Captured",Toast.LENGTH_SHORT).show();
unLockFocus();
}
};
mCameraCaptureSession.capture(
captureStillBuilder.build(),captureCallback,null
);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private int getOrientation(int rotation) {
return (ORIENTATIONS.get(rotation) + mSensorOrientation +180) % 360;
}
}
setupCamera() is called right from onSurfaceTextureAvailable, which can be earlier than the permissions are granted.
What you need to do is to track whether the permissions are granted and if the surface texture available in both callbacks.
Make a single entry for checking these conditions and setting up camera
private boolean mSurfaceTextureAvailable;
private boolean mPermissionsGranted;
private boolean mCameraOpened;
private void setupCameraIfPossible() {
if (!mCameraOpened && mSurfaceTextureAvailable && mPermissionsGranted) {
String cameraLens = BleUtils.getCameraLens(AndroidCamera.this);
if (TextUtils.isEmpty(cameraLens)) {
cameraLens = "1";
}
setupCamera(mTextureView.getWidth(), mTextureView.getHeight(), cameraLens);
openCamera();
}
}
private final TextureView.SurfaceTextureListener mSurfaceTextureListener =
new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurfaceTextureAvailable = true;
setupCameraIfPossible();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
//closeCamera();
mSurfaceTextureAvailable = false;
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_activity);
openBackgroundThread();
// Make sure the boolean flag is set. Will be true for lower SDK
mPermissionsGranted = hasAllPermissions(this, PERMISSIONS);
if (!mPermissionsGranted) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
mTextureView = (TextureView) findViewById(R.id.texture);
}
In onResume() you don't need to check for permissions. If they will be denied while in background your Activity will get killed and you will go through onCreate() again.
Remove the code in onPause() and onResume()!
// #Override
// public void onResume() {
// super.onResume();
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
// if(!hasAllPermissions(this, PERMISSIONS)){
// ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
// }
// }
// openBackgroundThread();
// if (mTextureView.isAvailable()) {
// if (!TextUtils.isEmpty(BleUtils.getCameraLens(AndroidCamera.this)))
// setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),BleUtils.getCameraLens(AndroidCamera.this));
// else
// setupCamera(mTextureView.getWidth(), mTextureView.getHeight(),"1");
// closeCamera();
// openCamera();
// } else {
// mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
// }
// }
// public void onPause() {
// Log.d(TAG,"onPause");
// closeCamera();
//
// closeBackgroundThread();
// super.onPause();
// }
Add this to onStart()
#Override
public void onStart() {
super.onStart();
openCameraIfPossible();
}
Move closing camera to onStop()
#Override
public void onStop() {
super.onStop();
closeCamera();
}
private void closeCamera() {
mCameraOpened = false; // set a field indicating it is closed
...
}
private void openCamera() {
...
mCameraOpened = true; // If successful, set a field indicating it is opened
}
Now another thing I discovered is that you must actually check for permissions in onRequestPermissionsResult() instead of using grantResults flags
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_CAMERA_RESULT:
mPermissionsGranted = hasAllPermissions(this, PERMISSIONS);
setupCameraIfPossible();
break;
default:
break;
}
}

Categories

Resources