How to take picture using inside Camera app - android

I want to take picture using camera app built in the device with touch event even though device doesn't support that function.
What i want to realize is following.
1) When I open the native or any other camera app,
2) Take a picture with touch event instead of camera button ( This part is what i want to develop)
Below code is What I try for this.
I tried to call transparent Activity on the camera app,
and When I get a touch event on the that Activity,
I call Take_picture() function.
But camera.takePicture() function in the Take_picture doesn't work. ( actually it doesn't call jpegCallback function)
private void Take_picture(){
camera = Camera.open();
if(camera != null)
{
camera.takePicture(null, null, jpegCallback);
}
}
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
new SaveImageTask().execute(data);
}
};
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
#Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
System.out.println("66666");
// Write to SD Card
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/camtest");
dir.mkdirs();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(dir, fileName);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
//Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to " + outFile.getAbsolutePath());
//refreshGallery(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
I couldn't get any information How to I control native camera app for take picture instantly.
Please help.

How to I control native camera app for take picture instantly.
You can't. You are welcome to create your own camera app that takes pictures however you want. The authors of other camera applications are welcome to implement their camera apps however they want, and they do not have to provide any means for other developers to dictate when and how the pictures are taken.
But camera.takePicture() function in the Take_picture doesn't work
Your app should be crashing, as you should not have a valid Camera object. Only one app can use the camera at a time.

Related

Unable to save Photos taken by camera on SD Card

I have an app that uses the Camera API, and it takes a photo with the call
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
mCamera.takePicture(shutterCallback, rawCallback, mPicture);
mCamera.startPreview();
mPicture is defined as
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " /* +
e.getMessage()*/);
Toast.makeText(MainActivity.this, "Failed to write Photo to File", Toast.LENGTH_SHORT);
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
Toast.makeText(MainActivity.this, "Writing Photo to File", Toast.LENGTH_SHORT);
fos.write(data);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
public static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/camtest");
dir.mkdirs();
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
mediaFile = new File(dir, "IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
Why isn't any pictures saved? I went to my gallery & file manager app to check, nothing.
I also noticed that my app crashes when I exit the app, could that be why?
My onPause method is as follows
#Override
protected void onPause() {
mSensorManager.unregisterListener(mShakeDetector);
letGo();
super.onPause();
}
private void letGo(){
if(mCamera != null){
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
cameraPreview.getHolder().removeCallback(cameraPreview);
mCamera.release();
mCamera = null;
}
}
Why isn't any pictures saved?
It is entirely possible that they are being saved. However, bear in mind that you are doing disk I/O on the main application thread; depending on StrictMode settings, you may be crashing due to this I/O.
If the pictures are not being saved, you should be seeing your log messages in LogCat. I recommend switching them to error severity (Log.e()), though.
I went to my gallery & file manager app to check, nothing.
They will not show up in a device "gallery"-style app, or in your desktop OS's file manager, for quite some time. That is because those tools use the MediaStore to see what exists, and you have not arranged to have your file be indexed by the MediaStore. To do that, use MediaScannerConnection and its scanFile() method.
I also noticed that my app crashes when I exit the app
Use LogCat to examine the Java stack trace associated with your crash.

Android onPictureTaken resulting in poor quality/wrong rotated images

I have an issue when saving images in my application. I am using Android camera api 1 (pre api 21) on android version 4.4.4. Device is a OnePlus One.
When I take a picture my in-built camera in my app in seems to save the images in poor quality and also rotated 90 degrees counter-clockwise (-90).
Here is an example with images.
Portrait view with default android camera app (saved image):
Portrait view with in-built app camera:
Picture when saved with in-built app camera (saved image):
First problem, rotation orientation
Now the rotation I am guessing is due to this (if I don't change the setDisplayOrientation the camera is skewed in my app):
public void refreshCamera(Camera camera) {
if (holder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
int rotation = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
// specifically for back facing camera
switch (rotation) {
case Surface.ROTATION_0:
degrees = 90;
break;
case Surface.ROTATION_90:
degrees = 0;
break;
case Surface.ROTATION_180:
degrees = 270;
break;
case Surface.ROTATION_270:
degrees = 180;
break;
}
camera.setDisplayOrientation(degrees);
setCamera(camera);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
To fix this I guess I could rotate the images when I have saved the image, seems like a waste of code writing such a method though.
Second problem, the quality
This I am clueless as to why the quality is so bad, I'm guessing it has to do with this:
private PictureCallback getPictureCallback() {
return new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// save picture on seperate thread so camera can refresh quicker
new Thread(new SavePicThread(data)).start();
// refresh camera to continue preview
cameraPreview.refreshCamera(camera);
}
};
}
public class SavePicThread implements Runnable {
byte[] data;
public SavePicThread(byte[] data) {
this.data = data;
}
public void run() {
// make a new picture file
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
// write to the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.flush();
fos.close();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast toast = Toast.makeText(getActivity(), "Picture saved", Toast.LENGTH_SHORT);
toast.show();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// make the picture visible to the rest of the device
galleryAddPic(pictureFile);
}
}
// make picture and save to a folder
private File getOutputMediaFile() {
// make a new file directory inside the "sdcard" folder
// File mediaStorageDir = new File("/sdcard/", "fela"); // private pic for app
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "fela");
// if the directory does not exist
if (!mediaStorageDir.exists()) {
// if you cannot make this directory return
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// take the current timeStamp
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
// and make a media file:
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
/**
* makes the image visible for the device (gallery)
* #param pic file
*/
private void galleryAddPic(File file) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
getActivity().sendBroadcast(mediaScanIntent);
}
Been looking at tutorials, this is pretty much what they cover!
I understand that you found the solution for image quality. Indeed, you cannot assume that the default PictureSize is the best quality available on the device; you should use getSupportedPictureSizes() and after that call setPictureSize().
Regarding rotation, the situation is more cumbersome. Camera parameters support the setRotation() method which
Sets the clockwise rotation angle in degrees relative to the orientation of the camera. This affects the pictures returned from JPEG Camera.PictureCallback. The camera driver may set orientation in the EXIF header without rotating the picture. Or the driver may rotate the picture and the EXIF thumbnail. If the Jpeg picture is rotated, the orientation in the EXIF header will be missing or 1 (row #0 is top and column #0 is left side).
As you can see from the description, some devices will actually save the JPEG image oriented correctly, but other devices will only save the EXIF header.
Unfortunately, the orientation flag is not enough for many image viewer apps, for example - for Windows built-in image preview. Performing rotation of the full-size image programmatically is possible, but it is a time- and (more importantly) memory-consuming task. The easiest way is to create a bitmap and rotate it.
Many people use scaled bitmap to make rotation faster and use less memory. But this will inevitably defeat your purpose of getting the best picture quality.

android byte[] data modification

I did my own camera app on Android.
1) Configuring camera and preview :
Camera.Parameters parameters = camera.getParameters();
// My camera takes landscape picture by befault (Samsung GT-9300).
// But my app is only in portrait mode.
camera.setDisplayOrientation(90);
// Here to rotate final pict
parameters.set("rotation", 90);
// Some code to define best preview resolution and best picture resolution
... some code ...
// Apply
camera.setParameters(parameters);
2) StartPreview
// Here I see what i want to see... Is there no problem here.
camera.startPreview();
3) GetOutputMediaFile()
// private function to create empty file which will receive data
private static File getOutputMediaFile(){
String NewFolder = "/TEST";
String StorageDirectory;
StorageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File mediaStorageDir = new File(StorageDirectory + NewFolder);
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d("myApp", "failed to create directory");
return null;
} else {
mediaStorageDir.mkdir();
}
}
String date = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.FRANCE).format(new Date());
File photo = new File(StorageDirectory + NewFolder, "photo_" + date + ".jpg");
return photo;
}
4) Here my problem
// camera.takePicture(null, null, mPicture) called on onCreate function
// Here this callback
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
pictureFile = getOutputMediaFile();
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " + e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
};
On my phone, if i go on my gallery, or original my files app, i have thumbnail and photo correctly oriented.
Now if I go, with Root File Manager, on this picture folder, thumbnail is oriented by default (real camera orientation), and same as if I look my picture with my computer.
Then I think my data var (byte[] data) on my onPictureTaken function is not good.
I think data is like that :
How I think my var data is
But I would like to have that as my var data :
How I would like to have
I know my var data is only byte[] but these cat pictures is to shows how I see my data var.
Now my questions :
A) Have I right on how my data variable is ?
B) If yes, can you say me how to do 90° rotation on this "array" ?
You should not change the image bits to account for rotation.
Rotation is stored in the JPG EXIF image metadata orientation value, so you just need to set the metadata value to match the camera orientation. Read more about this EXIF value and others here.
To manage the EXIF data you can use framework class ExifInterface.
If the picture shows correctly in your phone's gallery application, it is likely correctly oriented. You can experiment with different values for the Parameters.setRotation and see if they affect what you see in the gallery app.
Some picture viewing programs do not correctly apply the EXIF orientation field, which can lead to them drawing the image incorrectly rotated. If that's the case, changing the orientation field does nothing, since those programs will not work with any orientation value. You'll have to actually rotate the JPEG image, instead of just setting the metadata field, to get them to look correct there.
If you want to do this inside Android, you'll have to decode the byte[] you receive from the camera to a Bitmap (with a BitmapFactory.decodeByteArray, rotate the bitmap, and save the result as a JPEG. You'll lose all the other EXIF metadata (date/time taken, etc) unless you use ExifInterface to write them back. It's also possible to losslessly rotate a JPEG, but I don't know if there are Android libraries for that.

How to ensure JpegCallback is finished writing before trying to access the picture

I'm writing an application with one of the key features being taking a photo and writing it to a file, then reading that photo into a base64 array (all in the one button click). The problem being that when i initiate the onclick to take a photo it will return from this function before the onPhotoTaken() function has received the image and written it to the storage directory specified.
I have added log outputs at several stages in the code and it is clear that the onclick takePhoto function is exiting before the onPhotoTaken() function that it calls is finished.
The android documentation states that you need to wait for JpegCallback to finish returning before you can restart the preview but I am having trouble getting it to wait for the write to finish.
code:
public static void takePhoto(){
fCamera.takePicture(null, null, jpegCallback);
Log.d("capture", "photo was captured");
// Set the image callback
Log.d("this one is", "being called");
}
static PictureCallback jpegCallback = new Camera.PictureCallback() {
// Function for handling the picture
public void onPictureTaken(byte[] data, Camera fCamera){
//fCamera.stopPreview();
Log.d("is this", "not being called ??? probably");
File imagePath;
FileOutputStream out = null;
// create the filename with extension
String fileName = "IMAGE_1.bmp";
// Create / Find the storage Directory for our pictures
//storageDir = context.getDir("imageDir", Context.MODE_PRIVATE);
// Create it if it doesn't exist
// Create the image file
imagePath = new File(storageDir, fileName);
String finalPath = imagePath.getAbsolutePath();
Log.d("location", finalPath);
if (!imagePath.exists()) {
if (!imagePath.mkdirs())
Log.d("#string/app_name", "Failed to create File");
return;
}
try {
out = new FileOutputStream(imagePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//finalImage.compress(CompressFormat.PNG, 100, out);
try {
out.write(data);
Log.d("write", "photo was written");
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
Log cat:
10-13 12:55:39.185: D/capture(7126): photo was captured
10-13 12:55:39.185: D/this one is(7126): being called
These are the only log outputs that occur.
I have the same problem, by taking a photo and then try to create a thumbnail and store it to the media gallery.
As it's defined in here(developer.android.com/reference/android/hardware/Camera.html#takePicture) takePicture is an asynchronous proccess, so you have to derive your program logic and mandate the sequence.
This can be implemented with AsyncTask (http://developer.android.com/reference/android/os/AsyncTask.html)
In this example, the code inside onPostExecute method will be executed after camera.takePicture (so you are sure that onPictureTaken from PictureCallback is done).

How to capture a photo from the camera without intent

I want my app to be able to capture photos without using another application. The code i used :
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photo = null;
try
{
photo = this.createTemporaryFile("picture", ".jpg");
photo.delete();
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
mImageUri = Uri.fromFile(photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
But this code uses the phone's main camera app. Can anyone give me some code ?
Taking a picture directly using the Camera class is insanely complicated to get right.
I am working on a library to simplify this, where you just add a CameraFragment to your app for the basic preview UI, and call takePicture() on it to take a picture, with various ways to configure the behavior (e.g., where the pictures get saved). However, this library is still a work in progress.
Can anyone give me some code ?
"Some code" is going to be thousands of lines long (for a complete implementation, including dealing with various device-specific oddities).
You are welcome to read the Android developer documentation on the subject.
once you have the camera preview set, you need to do the following...
protected static final int MEDIA_TYPE_IMAGE = 0;
public void capture(View v)
{
PictureCallback pictureCB = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera cam) {
File picFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (picFile == null) {
Log.e(TAG, "Couldn't create media file; check storage permissions?");
return;
}
try {
FileOutputStream fos = new FileOutputStream(picFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "File not found: " + e.getMessage());
e.getStackTrace();
} catch (IOException e) {
Log.e(TAG, "I/O error writing file: " + e.getMessage());
e.getStackTrace();
}
}
};
camera.takePicture(null, null, pictureCB);
}
And the getOutputMediaFile function:
private File getOutputMediaFile(int type)
{
File dir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), getPackageName());
if (!dir.exists())
{
if (!dir.mkdirs())
{
Log.e(TAG, "Failed to create storage directory.");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyMMdd_HHmmss", Locale.UK).format(new Date());
if (type == MEDIA_TYPE_IMAGE)
{
return new File(dir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
}
else
{
return null;
}
}
And you are done!!!
found it here
Camera was deprecated in API 21, the new way is the use android.hardware.camera2.
To enumerate, query, and open available camera devices, obtain a CameraManager instance.
To quickly summarize:
Obtain a camera manager instance by calling Context.getSystemService(String)
Get a string[] of device camera IDs by calling CameraManager.GetCameraIdList().
Call CameraManager.OpenCamera(...) with the desired camera ID from the previous step.
Once the camera is opened, the callback provided in OpenCamera(...) will be called.

Categories

Resources