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.
Related
What am I doing wrong here? I'm trying to call the intent to get a picture in full size:
takePictureIntent
private void takePictureIntent(int request) {
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
File file = null;
try {
file = createImageFile(request);
} catch (Exception e) {
showErrorDialog(getString(R.string.error), getString(R.string.error_saving_picture));
Log.e(TAG, "Error while creating image file.");
}
if (file != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(takePictureIntent, request);
} else {
Log.e(TAG, "Error while creating image file.");
showErrorDialog(getString(R.string.error), getString(R.string.error_saving_picture));
}
}
}
createImageFile
private File createImageFile(final int request) {
final File storageDir = new File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES), getString(R.string.app_name));
if (!storageDir.exists()) {
if (!storageDir.mkdirs()) {
Log.e(TAG, "Cannot create parent folders.");
return null;
}
}
File file = null;
try {
file = File.createTempFile("test_", ".jpg", storageDir);
} catch (Exception e) {
Log.e(TAG, "Error while creating temp file.");
}
fileProduct = file;
return file;
}
onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_PRODUCT) {
if (fileProduct == null ||!fileProduct.exists() ||fileProduct.length() == 0) {
showErrorDialog(getString(R.string.error), getString(R.string.error_taking_product_picture));
return;
}
}
Sometimes (yes, sometimes) the length of the resulting file is 0. I know for sure that the folders in private app context exist and the image files as well (with length > 0). Could you please provide some help? I'm on 6.0 on Nexus 5X.
I would start by getting rid of File.createTempFile(). You do not need it, it wastes time, and it might cause some camera apps to want to not store the photo in that file (since the file is already there). Just generate a unique filename yourself. This will incrementally help with your compatibility.
Also, you need to make sure that you are holding onto fileProduct in the saved instance state Bundle, as your app's process may be terminated while the camera app is in the foreground.
However, in general, ACTION_IMAGE_CAPTURE is not very reliable. You are delegating the work to one of hundreds of possible camera apps, and some of those apps have bugs. One such bug is ignoring EXTRA_OUTPUT. So, in onActivityResult(), if you determine that you have a valid fileProduct value, but there is no file there, call data.getData() and see if you have a Uri there. In that case, the camera app may have stored the photo at the location identified by that Uri, and you can use ContentResolver and DocumentFile to try to work with that Uri.
Using this:
final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
file = new File(storageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
instead of
File.createTempFile()
magically seems to fix the problem. Thanks to CommonsWare for (somehow) pointing me in the right direction.
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.
I have a custom camera Android application that saves captured images, according to the Google tutorials, into the external memory, then Media Scanner triggers Gallery to detect them.
But I have a new client with LG G2 that has no SD card slot, not external memory -- only internal.
I explained to him that I can only make my app store the images in internal Cache of the app, and he would access them through Root Explorer of some kind.
But he asserts that other purchased camera apps store their images so that Gallery can detect them. HOW? Please help -- I need to make my app able to do that as well.
Thanks!
UPD: Following is my code that works for other devices and deals primarily with external memory:
public static File getBaseFolder() {
File f;
f = null;
try {
f = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
} catch (Exception e) {
Utils.toasterLong("Error accessing storage: " + e.getMessage());
}
return f;
}
public static File getImageFolder() {
File f;
f = null;
try {
f = new File(getBaseFolder(), "Magic");
} catch (Exception e) {
Utils.toasterLong("Error accessing storage: " + e.getMessage());
}
return f;
}
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = getImageFolder();
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
and the part of code that writes the image to external memory and triggers the scanner:
{
pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
writeErrorDirty = true;
if (MyDebug.LOG)
Log.d(TAG,
"Error creating media file, check storage permissions");
} else if (MyDebug.LOG)
Log.d(TAG, "Valid path=" + pictureFile.getAbsolutePath());
FileOutputStream out = null;
try {
out = new FileOutputStream(pictureFile);
picTaken_mod.compress(Bitmap.CompressFormat.JPEG, 90, out);
} catch (Exception e) {
e.printStackTrace();
writeErrorDirty = true;
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
writeErrorDirty = true;
if (MyDebug.LOG)
Log.d(TAG,
"Error writing media file, check storage permissions");
}
} // end try
try {
MediaScannerConnection.scanFile(grandContext,
new String[] { pictureFile.getAbsolutePath() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
// now visible in gallery
}
});
} catch (Exception e) {
if (MyDebug.LOG)
Log.d(TAG,
"Error broadcasting the image: " + e.getMessage());
// writeErrorDirty = true;
}
}
But I have a new client with LG G2 that has no SD card slot, not external memory -- only internal.
You have both internal storage and external storage on that device. You may not have removable storage, but removable storage is not internal storage and it is not external storage.
Please understand that what the Android SDK refers to as internal storage and external storage is tied to the Android SDK as does not necessarily line up with what information is shown to the user (e.g., in Settings).
But he asserts that other purchased camera apps store their images so that Gallery can detect them. HOW?
They wrote the images to external storage, then used MediaScannerConnection to inform the Gallery and other apps that use the MediaStore ContentProvider that the files are there.
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.
I'm a problem when I using the MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA in the Intent. The camera starts correctly but it doesn't save the files in my specific folder "/photo". But when I use the MediaStore.ACTION_IMAGE_CAPTURE it works fine, but I can't use this because it take only one photo each time.
I need the camera starts and the user takes many photos. After he closes the camera and all photos are saved in my specific folder.
Thanks for your help.
Regards,
Marcelo
Source code:
public void startCamera() {
Intent takePictureIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
File file = null;
try {
file = createImageFile();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
} catch (IOException e) {
file = null;
Log.e(this.getClass().getName(), e.getMessage(), e);
}
activity.startActivity(takePictureIntent);
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = JPEG_FILE_PREFIX + timeStamp + JPEG_FILE_SUFFIX;
return new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/photo/", imageFileName);
}
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA This intent does not support activity results or specific intent file outputs. This intent is designed to simply open the camera. The functionality you seek does not exist natively in Android.