I hope you can fix my problem:
I have got a textureview to takes photos but when he capture photos, the file who need to contain the picture is empty. I don't know where and what is the problem. I just think that the problem is when the file is created. Thank you to help me.
This is a part of my code :
private void takePicture() throws CameraAccessException, IOException {
if(cameraDevice == null){
return;
}
CameraManager manager = (CameraManager) Objects.requireNonNull(getContext()).getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
int width = 640;
int height = 480;
if(jpegSizes!=null && jpegSizes.length>0){
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
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);
int rotation = Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
// First I get the path to gallery and crate new Album to my app
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
mImageFolder = new File(file, "Fluico");
if (!mImageFolder.exists()) {
if (!mImageFolder.mkdirs()) {
Log.d("Fluicophoto", "failed to create directory");
}
}
/*Second I cut mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
from onActivityCreated and add here with the new path from my Album*/
#SuppressLint("SimpleDateFormat") String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "IMAGE_" + timestamp + "_";
file = File.createTempFile(prepend, ".jpg", mImageFolder);
Toast.makeText(getContext(), "file need to be save", Toast.LENGTH_SHORT).show();
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
try {
save(bytes);
} finally {
image.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(getContext(), "saved", Toast.LENGTH_SHORT).show();
try{
createCameraPreview();
}catch (CameraAccessException e){
Toast.makeText(getContext(), "capture not comleted", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured( CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(getContext(), "capture not configured", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onConfigureFailed( CameraCaptureSession session) {
}
},mBackgroundHandler);
}
private void save(byte[] bytes) {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
outputStream.close();
Toast.makeText(getContext(), "it's good", Toast.LENGTH_SHORT).show();
}catch (IOException e){
Toast.makeText(getContext(), "file not found", Toast.LENGTH_SHORT).show();
}
}
Try with below code:
File myDir;
String fname;
String id = "123456";
int count = 0;
String root = Environment.getExternalStorageDirectory().toString();
myDir = new File(root + "/PhotoApp/" + id);
myDir.mkdirs();
count++;
counter.setText(String.valueOf(count));
fname = "" + id + "-" + count + ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete();
This code will create a folder PhotoApp and inside the folder, all the images will store.
You can get full code with the camera in my GitHub:
Link: https://github.com/abhishekhzb/quick_camera
Related
I am developing app using camera on fragment,so for camera I have used this library https://natario1.github.io/CameraView/home because I am using watermarks in camera, now I want to save pictures and videos to gallery, for pictures I have done with below code, for video I done research but not get a solution, for pictures this library is giving bitmap so pictures are saving perfectly but for video I can't figure out kindly help me.
Thank you
public class VideoPreviewActivity extends AppCompatActivity {
private VideoView videoView;
private static VideoResult videoResult;
private Button btnSaveVideo;
public static void setVideoResult(#Nullable VideoResult result) {
videoResult = result;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_preview);
final VideoResult result = videoResult;
if (result == null) {
finish();
return;
}
btnSaveVideo = findViewById(R.id.save_video);
videoView = findViewById(R.id.video);
videoView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
playVideo();
}
});
AspectRatio ratio = AspectRatio.of(result.getSize());
MediaController controller = new MediaController(this);
controller.setAnchorView(videoView);
controller.setMediaPlayer(videoView);
videoView.setMediaController(controller);
videoView.setVideoURI(Uri.fromFile(result.getFile()));
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
ViewGroup.LayoutParams lp = videoView.getLayoutParams();
float videoWidth = mp.getVideoWidth();
float videoHeight = mp.getVideoHeight();
float viewWidth = videoView.getWidth();
lp.height = (int) (viewWidth * (videoHeight / videoWidth));
videoView.setLayoutParams(lp);
playVideo();
if (result.isSnapshot()) {
// Log the real size for debugging reason.
Log.e("VideoPreview", "The video full size is " + videoWidth + "x" + videoHeight);
}
}
});
//Click this button to save video
btnSaveVideo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Calling 1st Method but not working
//SaveVideo(videoResult.getFile().toString());
//2nd method calling but still not working
saveVideoToInternalStorage(videoResult.getFile().toString());
}
});
}
void playVideo() {
if (!videoView.isPlaying()) {
videoView.start();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (!isChangingConfigurations()) {
setVideoResult(null);
}
}
//first method which I tried but not working
private void SaveVideo(Uri f) {
//I don't know what data type I have to pass in the methods parameters
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath();
File myDir = new File(root + "/Push Videos");
if (!myDir.exists()) {
myDir.mkdirs();
}
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Video-"+ n +".mp4";
File file = new File (myDir, fname);
if (file.exists ())
file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
Toast.makeText(VideoPreviewActivity.this, "PUSH Video Saved", Toast.LENGTH_LONG).show();
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//Tried this 2nd method but it is also not giving a desired result
//For saving Video...
private void saveVideoToInternalStorage (String filePath) {
File newfile;
try {
File currentFile = new File(filePath);
String fileName = currentFile.getName();
ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getDir("videoDir", Context.MODE_PRIVATE);
newfile = new File(directory.getAbsolutePath(), fileName);
if(currentFile.exists()){
InputStream in = new FileInputStream(currentFile);
OutputStream out = new FileOutputStream(newfile);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
scanner(filePath);
in.close();
out.close();
Log.v("", "Video file saved successfully.");
Toast.makeText(this, "Push Video Saved TO Gallery", Toast.LENGTH_SHORT).show();
}else{
Log.v("", "Video saving failed. Source file missing.");
}
} catch (Exception e) {
Log.d("Err ", "EXS " + e.getMessage());
e.printStackTrace();
}
}
}
I'm trying to capture an image via camera2 API, and i'm able to achieve it.
But the main problem is when i try to open that image on mobile phone it shows an error like "unsupported file format". Here's my code so far.
SimpleDateFormat s = new SimpleDateFormat("ddhhmmss");
String format = s.format(new Date());
private File file = new File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES)+"/"+"image_" + format + ".jpg");
protected void takePicture() {
if(null == cameraDevice) {
Log.e("tag", "cameraDevice is 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);
}
int width = 640;
int height = 480;
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));
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(CaptureImage.this, "Saved:" + file, Toast.LENGTH_SHORT).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();
}
}
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 {
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}
}
};
I want to add feature in my app to download a GIF Image from url to my phones storage.
How can I do this into my application
public class Download {
Context context;
String url;
ProgressDialog progressDailog;
public void saveImage(Context context, String url) {
this.context = context;
this.url = url;
progressDailog = new ProgressDialog(context);
progressDailog.setMax(100);
progressDailog.setMessage("Please wait...");
progressDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDailog.setCanceledOnTouchOutside(false);
progressDailog.show();
Glide.with(context).asBitmap()
.load(url)
.apply(new RequestOptions()
.diskCacheStrategyOf(DiskCacheStrategy.ALL)
.format(DecodeFormat.PREFER_ARGB_8888)
.override(Target.SIZE_ORIGINAL))
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
progressDailog.dismiss();
storeImage(resource);
//Log.d(TAG, "Image : " + resource);
}
});
}
private void storeImage(Bitmap image) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
Toast.makeText(context, "Image Downloaded", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
private File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Christmas"); /*getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Christmas/c");*/
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs())
return null;
}
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_MERRY_CHRISTMAS.jpg");
return mediaFile;
}
}
From this code I can download the normal Image but it did not works on GIF. The GIF image downloaded and it remains static
This snippet will help you to download gif using GLIDE
Glide.with(context)
.download(url)
.listener(new RequestListener<File>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
progressDailog.dismiss();
Toast.makeText(context, "Error saving", Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
progressDailog.dismiss();
try {
saveGifImage(context, getBytesFromFile(resource), createName(url));
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
}).submit();
createName function
public String createName(String url) {
String name = url.substring( url.lastIndexOf('/')+1, url.length());
String NoExt = name.substring(0, name.lastIndexOf('.'));
if(!ext.equals(".gif")){
name = NoExt + ".jpg";
}
return name;
}
getBytesFromFile function
public byte[] getBytesFromFile(File file) throws IOException {
long length = file.length();
if (length > Integer.MAX_VALUE) {
throw new IOException("File is too large!");
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
InputStream is = new FileInputStream(file);
try {
while (offset < bytes.length
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
} finally {
is.close();
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file " + file.getName());
}
return bytes;
}
saveGifImage function
public void saveGifImage(Context context, byte[] bytes, String imgName ) {
FileOutputStream fos = null;
try {
File externalStoragePublicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File customDownloadDirectory = new File(externalStoragePublicDirectory, "Merry_Christmas");
if (!customDownloadDirectory.exists()) {
boolean isFileMade = customDownloadDirectory.mkdirs();
}
if (customDownloadDirectory.exists()) {
File file = new File(customDownloadDirectory, imgName);
fos = new FileOutputStream(file);
fos.write(bytes);
fos.flush();
fos.close();
if (file != null) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, file.getName());
values.put(MediaStore.Images.Media.DISPLAY_NAME, file.getName());
values.put(MediaStore.Images.Media.DESCRIPTION, "");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/gif");
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
ContentResolver contentResolver = context.getContentResolver();
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Toast.makeText(context, "Image saved to " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
For getting GIF using Glide:
Glide.with(MainActivity.this).asFile()
.load(url)
.apply(new RequestOptions()
.format(DecodeFormat.PREFER_ARGB_8888)
.override(Target.SIZE_ORIGINAL))
.into(new Target<File>() {
#Override
public void onStart() {
}
#Override
public void onStop() {
}
#Override
public void onDestroy() {
}
#Override
public void onLoadStarted(#Nullable Drawable placeholder) {
}
#Override
public void onLoadFailed(#Nullable Drawable errorDrawable) {
}
#Override
public void onResourceReady(#NonNull File resource, #Nullable Transition<? super File> transition) {
storeImage(resource);
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
}
#Override
public void getSize(#NonNull SizeReadyCallback cb) {
}
#Override
public void removeCallback(#NonNull SizeReadyCallback cb) {
}
#Override
public void setRequest(#Nullable Request request) {
}
#Nullable
#Override
public Request getRequest() {
return null;
}
});
For Saving Image:
private void storeImage(File image) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream output = new FileOutputStream(pictureFile);
FileInputStream input = new FileInputStream(image);
FileChannel inputChannel = input.getChannel();
FileChannel outputChannel = output.getChannel();
inputChannel.transferTo(0, inputChannel.size(), outputChannel);
output.close();
input.close();
Toast.makeText(MainActivity.this, "Image Downloaded", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Christmas"); /*getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Christmas/c");*/
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs())
return null;
}
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_MERRY_CHRISTMAS_"+Calendar.getInstance().getTimeInMillis() +".gif");
return mediaFile;
}
Glide can get File, worked with me:
Glide.with(context).asFile()
.load(url)
.apply(new RequestOptions()
.diskCacheStrategyOf(DiskCacheStrategy.ALL)
.format(DecodeFormat.PREFER_ARGB_8888)
.override(Target.SIZE_ORIGINAL))
.into(new SimpleTarget<File>() {
#Override
public void onResourceReady(#NonNull File resource, #Nullable Transition<? super File> transition) {
progressDailog.dismiss();
storeImage(resource);
//Log.d(TAG, "Image : " + resource);
}
});
I am trying to create a facial/emotion detection application for my dissertation and have hit the wall that has stopped me from progressing and I cant figure out the reason why it is preventing the image saving to the directory of the phone. It seems to be saving to the SD card, but I dont use an SDcard in my phone / an emulated DCIM.
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+ "/" + 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 (IOException e)
{
e.printStackTrace();
}
finally {
{
if (image != null)
image.close();
}
}
}
This is the code I have to create the file and save to the location, I have tried other solutions but they throw out errors.
File folder = new File(Environment.getExternalStorageDirectory() + "/CustomFolder");
File file;
if (!folder.exists()) {
boolean success = folder.mkdir();
if (success){
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}else {
Toast.makeText(FacialDetection.this, "Failed to save file to folder", Toast.LENGTH_SHORT).show();
}
}else{
file = new File(folder.getPath() + "/" + 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 (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(FacialDetection.this, "Saved " + ***file***, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
The updated code, stuff bold and italic is what is throwing errors
I will advise you to create your own custom folder location this way:
File folder = new File(Environment.getExternalStorageDirectory() + "/CustomFolder");
File file;
if (!folder.exists()) {
boolean success = folder.mkdir();
if (success){
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}else {
//Some message
}
}else {
file = new File(folder.getPath() + "/" + UUID.randomUUID(), toString()+ ".jpg");
}
//The rest of your code...
You're calling:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
I would speculate that .getExternalStoragePublicDirectory() means get directory on SD card. Is there a getInternal... method?
//Create folder !exist
String folderPath = Environment.getExternalStorageDirectory() +"/myFoldername";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
//create a new file
newFile = new File(folderPath, newPhoto.getName());
if (newFile != null) {
// save image here
Uri relativePath = Uri.fromFile(newFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, relativePath);
startActivityForResult(intent, CAMERA_REQUEST);
}
I use Android CAMERA 2 API for the camera2 supporting phones on my app. Works great, but some times it captures 0kb images & gives a full white preview. Shows no errors or warnings on logcat. Below is my camera image capture & save code:
protected void takePictureViaCamera2() {
if (null == cameraDevice) {
Log.e(TAG, "cameraDevice is 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);
}
int width = 640;
int height = 480;
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 file = new File(Environment.getExternalStorageDirectory()+"/pic.jpg");
final File file = createImageFile();
final String checkPath = file.getParent();
Log.e("checkPath", checkPath);
//photoFile = createImageFile();
//photoFilePath = photoFile.getParent();
//Log.e("photoFilePath", photoFilePath);
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();
Log.e("readerListenerFNF_EX", e + "");
} catch (IOException e) {
e.printStackTrace();
Log.e("readerListenerIO_EX", e + "");
} catch (Exception e) {
e.printStackTrace();
Log.e("readerListener_EX", e + "");
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream output = null;
try {
output = new FileOutputStream(file);
//output = new FileOutputStream(photoFile);
output.write(bytes);
} finally {
if (null != output) {
output.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(TravelChargesCamera2Activity.this, "Saved***:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
closeCamera();
Thread thread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(5000);
runOnUiThread(new Runnable() {
#Override
public void run() {
toolbar.setVisibility(View.VISIBLE);
header.setVisibility(View.VISIBLE);
assessorTraveldetails_scroll.setVisibility(View.VISIBLE);
camera2Layout.setVisibility(View.GONE);
try {
if (!file.getParentFile().isDirectory()) {
travelDirectory = new File(checkPath);
Log.e("travelDir==created==", travelDirectory + "");
} else {
travelDirectory = file.getParentFile();
Log.e("travelDir==exists==", travelDirectory + "");
}
files = travelDirectory.listFiles();
Log.e("files", files + "");
// removes old images from view
// prevents display duplication
travelGallery.removeAllViews();
// loop displays the photos captured on Horizontal ScrollView
for (File picFile : files) {
travelGallery.addView(insertPhoto(picFile.getAbsolutePath()));
byte[] byteArray = ImageUtils.fileToByteArray(file);
Log.e("byteArray", byteArray + "");
}
} catch (Exception e) {
e.printStackTrace();
Log.e("file", e + "");
}
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("InterruptedException", e + "");
} catch (Exception e) {
e.printStackTrace();
Log.e("Exception", e + "");
}
}
};
thread.start();
}
};
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();
Log.e("CameraAccessException", e + "");
} catch (Exception e) {
e.printStackTrace();
Log.e("takePictureViaCamera2", e + "");
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String uniqueId = UUID.randomUUID().toString();
String imageFileName = "CAP_" + timeStamp + "_" + uniqueId;
String bCode = "";
masterMap = (LinkedTreeMap) gson.fromJson(batchMasterObject.getMasterJson(), Object.class);
auditMap = (LinkedTreeMap) masterMap.get("2001");
if ((auditMap.get("batchCode") != null && !auditMap.get("batchCode").equals(""))) {
bCode = auditMap.get("batchCode").toString();
} else if (auditMap.get("cbc") != null && !auditMap.get("cbc").equals("")) {
bCode = auditMap.get("cbc").toString();
}
File storageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "/" + bCode + "/Travel/");
if (!storageDir.exists()) {
storageDir.mkdirs();
}
String checkPath = storageDir.getPath();
Log.e("checkPath", checkPath);
Toast.makeText(getApplicationContext(), checkPath, Toast.LENGTH_LONG).show();
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = storageDir.getAbsolutePath();
return image;
}
Could any one help on this?
NOTE: The camera, captures and stores an image file as intended, but the file size is 0kb. When the image file is opened on phone or pc, it says "Unsupported format"
It looks like you're taking your final JPEG capture as the very first frame.
This means the camera's auto-exposure routines have not had any time to work (since you're grabbing the first frame), so the image will be captured with the initial settings hardcoded into the camera driver. This may work for some scenes, but in others, the image will be far too bright or far too dark.
For best results, you should first let the camera meter for a while, until auto-exposure and auto-focus are converged.
Generally, this can be done by setting up a low-resolution preview output (use a SurfaceTexture for example), and running it for a second or two (or wait until a CaptureResult has an AE_STATE of CONVERGED). Then issue the JPEG capture.