I am trying to integrate camera access to my android application.My requirements are making a preview of the photo taken and store the same on the SD card.But making a preview and storing on the sd card are working fine separately.But when i integrate both into a single application it doesnt work.And i am using the standard code given in the developer site for my storage on SD card.
here is my code
public void pickImage(View View) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
startActivityForResult(intent, REQUEST_CODE);
}
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
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 = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Sparikko");
// 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("Sparikko", "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 {
return null;
}
return mediaFile;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
try {
// We need to recyle unused bitmaps
if (bitmap != null) {
bitmap.recycle();
}
InputStream stream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(stream);
stream.close();
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
super.onActivityResult(requestCode, resultCode, data);
}
I am getting a application is stopped unexpectedly error.And i used logcat to find where i could find the program control where the error happens.And i found that the error happens in InputStream stream = getContentResolver().openInputStream(data.getData()); line in the onActivityResult() function.Both funcationality works fine seperately bt giving error when combined.
after taking picture from camera you need to downscale bitmap to set on ImageView to show preview. refer below method:
private void showAttachedImagePreview(String imagePath)
{
Bitmap bitmap = null;
//= BitmapFactory.decodeFile(imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
try
{
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e)
{
e.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 2;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e1)
{
e1.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 3;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e2)
{
e2.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 4;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e3)
{
e3.printStackTrace();
bitmap=null;
}
}
}
}
if(bitmap!=null)
{
commentAttachedImagePreview.setVisibility(ImageView.VISIBLE);
commentAttachedImagePreview.setImageBitmap(bitmap);
commentAttachedImageName.setVisibility(TextView.VISIBLE);
commentAttachedImageName.setText(new File(imagePath).getName());
deleteAttachedImage.setVisibility(ImageView.VISIBLE);
}
try
{
File file = new File(AppManager.getInstance().DATA_DIRECTORY, "tausif_tmp.png");
FileOutputStream outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
outStream.flush();
outStream.close();
filePath = file.getPath();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
Related
Please help me how to take a picture from a custom camera and display it on another activity, please give me more detailed answer, what code should i put, and where, please tell me if what kind of variables, int, strings, booleans should i create,
here is my code :
Main Activity :
#Override
public void onPictureTaken(byte[] data, Camera camera) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
// Store bitmap to local storage
FileOutputStream out = null;
try {
// Prepare file path to store bitmap
// This will create Pictures/MY_APP_NAME_DIR/
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MY_APP_NAME_DIR");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(Constants.LOG_TAG, "failed to create directory");
return null;
}
}
// Bitmap will be stored at /Pictures/MY_APP_NAME_DIR/YOUR_FILE_NAME.jpg
String filePath = mediaStorageDir.getPath() + File.separator + "YOUR_FILE_NAME.jpg";
out = new FileOutputStream(filePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can use interface to pass YOUR_FILE_PATH from CameraPreview class to MainActivity class.
then in MainActivity.java
Intent i = new Intent(this, EditPicture.class);
i.putExtra("FILE_PATH", YOUR_FILE_PATH);
startActivity(i);
in EditPicture activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().hasExtra("FILE_PATH")) {
String filePath = getIntent().getStringExtra("FILE_PATH");
// Read bitmap from local file
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
yourImageView.setImageBitmap(bitmap);
}
}
Finally, add <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> to your AndroidManifest.xml in order to allow your app writing to external storage.
This is the example of how to write bitmap to external storage. If you want to store to internal storage such as cache or other options, please refer to http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Let me know if you need me to elaborate more.
I am building an Android app that takes photos, then uploads them to a Rails API.
The api expects the base64 encoded raw file bytes, to be stored as a temp file representing the image in JPG format.
However, the API is rejecting the uploaded file with this error message:
<Paperclip::Errors::NotIdentifiedByImageMagickError:
This seems to be due to a failure of encoding on the part of the Android app.
The base64 image bytes that I'm sending up look like this:
Which appears invalid just by looking at it.
The image is created in android by taking a pic with the Camera API and base64 encoding the resulting byteArray:
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
Anyone know what I'm doing wrong here?
On button click for capturing an image from a camera use this
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
((Activity) context).startActivityForResult(intent, Constants.REQUEST_IMAGE_CAPTURE);
and on activityResult of the activity implement the following code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
final ImageView uploadArea = (ImageView) attachmentDialog.findViewById(R.id.uploadArea);
Bitmap bitmap;
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles()) {
if (temp.getName().equals("temp.jpg")) {
f = temp;
break;
}
}
try {
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),
bitmapOptions);
Matrix matrix = new Matrix();
matrix.postRotate(-90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] attachmentBytes = byteArrayOutputStream.toByteArray();
String attachmentData = Base64.encodeToString(attachmentBytes, Base64.DEFAULT);
uploadArea.setImageBitmap(rotatedBitmap);
String path = android.os.Environment
.getExternalStorageDirectory()
+ File.separator
+ "CTSTemp" + File.separator + "default";
f.delete();
OutputStream outFile = null;
File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
try {
outFile = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outFile);
outFile.flush();
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I hope this will help you, and for any farther info, please ask
i am using the API21 SlidingTabLayout and SlidingTabStrips for my application.
I am saving an .tmp file of my intent camera photo. that works fine and i can see it on my phone package directory but i can store this .tmp file as .png ( i want to change the resolution because i need <1mb files instead of the 3mb files from the photo API intent)
i tried so many things in the last two hours and i can't solve it.
here is my code:
starting the intent with: takeAPicture
private void takeAPicture(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(getView().getContext())));
startActivityForResult(intent, TAKE_PHOTO_CODE);
}
the path of my .tmp file: getTempFile
private File getTempFile(Context context){
final File path = new File(Environment.getExternalStorageDirectory(), getView().getContext().getPackageName());
if(!path.exists()){
path.mkdir();
}
return new File(path, "test.tmp");
}
at least i handle the ActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "onActivityResult: Joined");
if(resultCode == Activity.RESULT_OK){
switch (requestCode){
case TAKE_PHOTO_CODE:
final File file = getTempFile(getView().getContext());
Toast.makeText(getActivity().getApplicationContext(), "Uri: " + Uri.fromFile(file), Toast.LENGTH_LONG);
try{
Bitmap captureBmp = MediaStore.Images.Media.getBitmap(getActivity().getApplicationContext().getContentResolver(), Uri.fromFile(file));
FileOutputStream fos = new FileOutputStream(new File(new File(Environment.getExternalStorageDirectory(), getView().getContext().getPackageName()),"done.png"));
captureBmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
The fact is, the .tmp file is stored and the uri for
Bitmap captureBmp = MediaStore.Images.Media.getBitmap(getActivity().getApplicationContext().getContentResolver(), Uri.fromFile(file));
is correct.
hope someone can help me
You can use my code:
public static boolean saveImage(Context context, byte[] image, String filename) {
Bitmap bitmapImage = BitmapFactory.decodeByteArray(image, 0, image.length);
return saveImage(context, bitmapImage, filename);
}
public static boolean saveImage(Context context, Bitmap image, String filename) {
try {
FileOutputStream fos = context.openFileOutput(filename,Context.MODE_PRIVATE);
imagem.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
File file = context.getFileStreamPath(filename);
} catch (Exception e) {
return false;
}
return true;
}
i have an issue, i'm using the following code to take a picture:
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
the function to create the fileUri is this:
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/*
* returning image / video
*/
private static File getOutputMediaFile(int type) {
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Creación fallida "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMGTRAF_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VIDTRAF_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
and here i'm showing the image on a ImageView:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// if the result is capturing Image
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// successfully captured the image
// display it in image view
previewCapturedImage();
Toast.makeText(getApplicationContext(),
"Mostrando foto", Toast.LENGTH_SHORT)
.show();
} else if (resultCode == RESULT_CANCELED) {
// user cancelled Image capture
Toast.makeText(getApplicationContext(),
"Acción cancelada", Toast.LENGTH_SHORT)
.show();
} else {
// failed to capture image
Toast.makeText(getApplicationContext(),
"Error al capturar la imagen", Toast.LENGTH_SHORT)
.show();
}
} else if (requestCode == CAMERA_CAPTURE_VIDEO_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// video successfully recorded
// preview the recorded video
previewVideo();
Toast.makeText(getApplicationContext(),
"Reproduciendo video", Toast.LENGTH_SHORT)
.show();
} else if (resultCode == RESULT_CANCELED) {
// user cancelled recording
Toast.makeText(getApplicationContext(),
"Acción cancelada", Toast.LENGTH_SHORT)
.show();
} else {
// failed to record video
Toast.makeText(getApplicationContext(),
"Error al capturar el video", Toast.LENGTH_SHORT)
.show();
}
}
}
/*
* Display image from a path to ImageView
*/
private void previewCapturedImage() {
try {
// hide video preview
videoPreview.setVisibility(View.GONE);
imgPreview.setVisibility(View.VISIBLE);
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
// downsizing image as it throws OutOfMemory Exception for larger
// images
options.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
imgPreview.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
The problem is that when i capture the image it's being saved in it's original size (1954*2560) and when i upload it to the server takes a very long time. I've saw many questions and answers here but none worked for me. I want to take the photo, resize it to 800x600 and then save it again so i can upload it to the server.
How can i achieve that? Please consider that i'm very new to Android programming.
Thanks!
Finally i've resolved the problem by doing:
private void previewCapturedImage() {
try {
// hide video preview
videoPreview.setVisibility(View.GONE);
imgPreview.setVisibility(View.VISIBLE);
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
// downsizing image as it throws OutOfMemory Exception for larger
// images
options.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File file;
file = new File(fileUri.getPath());
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
//fileUri = file;
imgPreview.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
I hope it helps someone in the near future.
Solved with this:
private void previewCapturedImage() {
try {
// hide video preview
videoPreview.setVisibility(View.GONE);
imgPreview.setVisibility(View.VISIBLE);
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
// downsizing image as it throws OutOfMemory Exception for larger
// images
options.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File file;
file = new File(fileUri.getPath());
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
//fileUri = file;
imgPreview.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
I've been busting my head on this, and not so sure what to do. What I am trying to do is: Take a picture, compress it to png (keeping the original dimensions), and then save it to sdCard. The reason why I need to do this is because I have to recompress it again, then Base64 encode it so i can send it to a server. The problem is 1. the file is too big 2. i am running out of memory and 3. not sure if I am doing this correctly.
Thanks for your help
Here is my code:
#Override
public void onClick(View button) {
switch (button.getId()) {
case R.id.cameraButton:
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File("/sdcard/test.png")));
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
break;
case R.id.galleryButton:
sendToDatabase();
break;
}
}
// Camera on activity for result - save it as a bmp and place in imageview
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST) {
// do something
}
if (resultCode == Activity.RESULT_OK) {
Log.d(TAG, "result ok");
picture = BitmapFactory.decodeFile("/sdcard/test.png");
// Create string to place it in sd card
String extStorageDirectory = Environment
.getExternalStorageDirectory().toString();
//create output stream
OutputStream outputStream = null;
//create file
File file = new File(extStorageDirectory, "test.png");
try {
outputStream = new FileOutputStream(file);
picture.compress(Bitmap.CompressFormat.PNG, 80, outputStream);
//picture.recycle();
outputStream.flush();
outputStream.close();
} catch (IOException e){
Log.d(TAG, "ERROR");
}
imageView.setImageBitmap(picture);
}
}
public void sendToDatabase() {
InputStream inputStream = null;
//get the picture from location
picture = BitmapFactory.decodeFile("/sdcard/test.png");
// CONVERT:
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Boolean didItWork = picture.compress(Bitmap.CompressFormat.PNG, 50, outStream);
picture.recycle();
if (didItWork = true) {
Log.d(TAG, "compression worked");
}
Log.d(TAG, "AFTER. Height: " + picture.getHeight() + " Width: "
+ picture.getWidth());
final byte[] ba = outStream.toByteArray();
try {
outStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
When you do picture.compress(Bitmap.CompressFormat.PNG, 50, outStream); the compression wont work as PNG which is lossless, will ignore the quality setting. So the parameter 50 wont work in this case. So i suggest you to change CompressFormat.PNG to CompressFormat.JPEG.