I wrote some code to take a picture and save it on external storage. If I run the app, and make the picture I get File Not Found Exception.
Here is my code:
public class CameraActivity extends BaseActivity {
//variables for navigation drawer
private String[] navMenuTitles;
private TypedArray navMenuIcons;
//request code
private static final int ACTIVITY_START_CAMERA_APP = 1777;
//ImageView for the thumbnail
private ImageView mPhotoCapturedImageView;
//File for folder
private File folder;
//variable for timestamp
String timeStamp = "";
//Requestcode for external Storage Permission
final int REQ_CODE_EXTERNAL_STORAGE_PERMISSION = 42;
//FloatAction Button to save the picture
private FloatingActionButton save;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
/*
* Initialize nav draw items
*/
//load title from String.xml
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
//load icons from String.xml
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
//set title and icons
set(navMenuTitles, navMenuIcons);
//initialize ImageView
mPhotoCapturedImageView = (ImageView) findViewById(R.id.imgViewThumbNail);
//creat new intent for the camera app
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//creat and set a timestamp
timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
//check if permission granted
if (ActivityCompat.checkSelfPermission(CameraActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
if (folder == null) {
createFolder();
}
} else {
ActivityCompat.requestPermissions(CameraActivity.this, new String[]
{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQ_CODE_EXTERNAL_STORAGE_PERMISSION);
}
/*
//create a file with timestamp as title and save it in the folder
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
File.separator + "MyIdea" + File.separator + "IdeaGallery" + File.separator +
"IMG_" + timeStamp + ".jpg"); */
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(folder));
//start the camera app
startActivityForResult(intent, ACTIVITY_START_CAMERA_APP);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Check that request code matches ours:
if (requestCode == ACTIVITY_START_CAMERA_APP)
{
File foto = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Pictures/", "MyIdea/IdeaGalery/" +
"IMG_" + timeStamp + ".jpg");
Bitmap bitmap = decodeSampledBitmapFromFile(foto.getPath(), 1000, 700);
mPhotoCapturedImageView.setImageBitmap(bitmap);
MediaScannerConnection.scanFile(CameraActivity.this, new String[]{foto.getPath()}, new String[]{"image/jpeg"}, null);
//Get our saved file into a bitmap object:
//File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +File.separator + "MyIdea" + File.separator + "IdeaGallery" + File.separator + "IMG_" + timeStamp + ".jpg");
//Bitmap photoCapturedBitmap = BitmapFactory.decodeFile(mImageFileLocation);
}
}
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight)
{ // BEST QUALITY MATCH
//First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize, Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.RGB_565;
int inSampleSize = 1;
if (height > reqHeight)
{
inSampleSize = Math.round((float)height / (float)reqHeight);
}
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth)
{
inSampleSize = Math.round((float)width / (float)reqWidth);
}
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
private void createFolder() {
folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/", "MyIdea/IdeaGalery/" +
"IMG_" + timeStamp + ".jpg");
folder.mkdir();
Toast.makeText(getApplicationContext(), "Folder created", Toast.LENGTH_LONG).show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQ_CODE_EXTERNAL_STORAGE_PERMISSION && grantResults.length > 0 &&
grantResults [0] == PackageManager.PERMISSION_GRANTED) {
createFolder();
}
}
}
The Permission at Android Manifest were set als
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Can somebody help please help me to find the bug?
I cleaned up my code and i hope you can better understand it. First i check, if folder exist, if not, i create it. Then i create a file for the image. Then I create an Uri from the image and set it to putExtra Method on at the intent.
On activity result, i read the uri from the data and wrap it to a string.
Here is my new code:
//check if imageFolder already exist
if (imageFolder == null) {
//create folder if don't exist
imageFolder = new File(Environment.getExternalStorageDirectory(), "MyIdea/IdeaGallery/");
imageFolder.mkdir();
}
//create imageFile
image = new File(imageFolder, "IMG_" + timeStamp + ".jpg");
//get the uri of the imageFile
Uri uriSavedImage = Uri.fromFile(image);
//put uri path of the image to the intent
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
//start the camera app
startActivityForResult(intent, ACTIVITY_START_CAMERA_APP);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Check that request code matches ours:
if (requestCode == ACTIVITY_START_CAMERA_APP)
{
if (resultCode == RESULT_OK) {
//Get our saved file into a bitmap object:
Bitmap bitmap = decodeSampledBitmapFromFile(String.valueOf(data.getData()), 1000, 700);
mPhotoCapturedImageView.setImageBitmap(bitmap);
MediaScannerConnection.scanFile(CameraActivity.this, new String[]{image.getPath()},
new String[]{"image/jpeg"}, null);
}
}
}
If i look at the Android Monitor, I cant find the FileNoTFound Exception. But if i check my device, i can't find any folders or images on it.
This messages ist showing on the Android Monitor:
08-22 12:41:08.302 17152-17196/com.example.dudi.myidea I/Adreno-EGL: : QUALCOMM Build: 10/21/15, 369a2ea, I96aee987eb
08-22 12:41:08.303 17152-17196/com.example.dudi.myidea I/OpenGLRenderer: Initialized EGL, version 1.4
08-22 12:41:08.827 17152-17189/com.example.dudi.myidea W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
08-22 12:41:08.882 17152-17152/com.example.dudi.myidea I/Choreographer: Skipped 37 frames! The application may be doing too much work on its main thread.
08-22 12:41:08.906 17152-17196/com.example.dudi.myidea V/RenderScript: 0xa00bc000 Launching thread(s), CPUs 4
Finaly I looked to Android Developer Tutorial and changed my code like the examples in tutorial. Now it works fine. Here my working code:
public class CameraActivity extends BaseActivity {
//variables for navigation drawer
private String[] navMenuTitles;
private TypedArray navMenuIcons;
//request code
private static final int ACTIVITY_START_CAMERA_APP = 1777;
//ImageView for the thumbnail
private ImageView mPhotoCapturedImageView;
//variable for timestamp
//String timeStamp = "";
private static final int MEDIA_TYPE_IMAGE = 1;
private Uri fileUri;
//File for folder
//private File imageFolder;
//File for image;
//private File image;
//FloatAction Button to save the picture
private FloatingActionButton save;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
/*
* Initialize nav draw items
*/
//load title from String.xml
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
//load icons from String.xml
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
//set title and icons
set(navMenuTitles, navMenuIcons);
//initialize ImageView
mPhotoCapturedImageView = (ImageView) findViewById(R.id.imgViewThumbNail);
//initialize Camera Intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//set file uri
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
//put Extra for onActivityResult
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//start camera app
startActivityForResult(intent, ACTIVITY_START_CAMERA_APP);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Check that request code matches ours
if (requestCode == ACTIVITY_START_CAMERA_APP)
{
if (resultCode == RESULT_OK) {
//Get our saved file into a bitmap object:
Bitmap bitmap = decodeSampledBitmapFromFile(fileUri.getPath(), 1000, 700);
mPhotoCapturedImageView.setImageBitmap(bitmap);
MediaScannerConnection.scanFile(CameraActivity.this, new String[]{fileUri.getPath()},
new String[]{"image/jpeg"}, null);
} else if (requestCode == RESULT_CANCELED) {
Toast.makeText(this, "Error, user cancelled the image capture", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Imagecapture failed.", Toast.LENGTH_LONG).show();
}
}
}
/* Create a file Uri for saving an image */
private static Uri getOutputMediaFileUri (int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/* Create a file to save an image */
private static File getOutputMediaFile(int type) {
//check if SD-Card is mounted
Boolean isMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
File mediaStorageDir = null;
if (isMounted) {
//create storage directory if does not exist
mediaStorageDir = new File (Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "IdeaGallery");
if (! mediaStorageDir.exists()) {
if (! mediaStorageDir.mkdir()) {
Log.d("IdeaGallery", "failed to create");
return null;
}
}
} else {
Log.d("IdeaGallery", "failed to create");
}
//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;
}
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight)
{ // BEST QUALITY MATCH
//First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize, Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.RGB_565;
int inSampleSize = 1;
if (height > reqHeight)
{
inSampleSize = Math.round((float)height / (float)reqHeight);
}
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth)
{
inSampleSize = Math.round((float)width / (float)reqWidth);
}
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
}
Related
I have to launch the camera, and when the users has done the picture, I have to take it and show it in a view.
Looking at http://developer.android.com/guide/topics/media/camera.html I have done:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bLaunchCamera = (Button) findViewById(R.id.launchCamera);
bLaunchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "lanzando camara");
//create intent to launch camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); //create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //set the image file name
//start camera
startActivityForResult(intent, CAMERA_REQUEST);
}
});
/**
* Create a File Uri for saving image (can be sued to save video to)
**/
private Uri getOutputMediaFileUri(int mediaTypeImage) {
return Uri.fromFile(getOutputMediaFile(mediaTypeImage));
}
/**
* Create a File for saving image (can be sued to save video to)
**/
private File getOutputMediaFile(int mediaType) {
//To be safe, is necessary to check if SDCard is mounted
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
(String) getResources().getText(R.string.app_name));
//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("ddMMyyyy_HHmmss").format(new Date());
File mediaFile;
if (mediaType == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == CAMERA_REQUEST) {
if(resultCode == RESULT_OK) {
//Image captured and saved to fileUri specified in Intent
Toast.makeText(this, "image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
Log.d(TAG, "lanzando camara");
} else if(resultCode == RESULT_CANCELED) {
//user cancelled the image capture;
Log.d(TAG, "usuario a cancelado la captura");
} else {
//image capture failed, advise user;
Log.d(TAG, "algo a fallado");
}
}
}
When the picture has been done, the app crashes when it try to send the 'Toast' info because 'data' is null.
But if I debug the app I can see that the image has been saved.
So my question is: How can I get the path in the onActivityResult?
The problem you are facing is that, whenever we select an image from camera intent, it may finish the activity which called it, so imageUri object you created will be null while you return.
so you need to save it when you exit the activity (to go to camera intent), like this -
/**
* Here we store the file url as it will be null after returning from camera
* app
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save file url in bundle as it will be null on screen orientation
// changes
outState.putParcelable("file_uri", mImageUri);
}
and retrieve it back when you come back to the activity -
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// get the file url
mImageUri = savedInstanceState.getParcelable("file_uri");
}
Your code looks fine, you only need to add this change in it.
Here is code I have used for Capturing and Saving Camera Image then display it to imageview. You can use according to your need.
You have to save Camera image to specific location then fetch from that location then convert it to byte-array.
Here is method for opening capturing camera image activity.
private static final int CAMERA_PHOTO = 111;
private Uri imageToUploadUri;
private void captureCameraImage() {
Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg");
chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
imageToUploadUri = Uri.fromFile(f);
startActivityForResult(chooserIntent, CAMERA_PHOTO);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) {
if(imageToUploadUri != null){
Uri selectedImage = imageToUploadUri;
getContentResolver().notifyChange(selectedImage, null);
Bitmap reducedSizeBitmap = getBitmap(imageToUploadUri.getPath());
if(reducedSizeBitmap != null){
ImgPhoto.setImageBitmap(reducedSizeBitmap);
Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
uploadImageButton.setVisibility(View.VISIBLE);
}else{
Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
}
}
}
Here is getBitmap() method used in onActivityResult(). I have done all performance improvement that can be possible while getting camera capture image bitmap.
private Bitmap getBitmap(String path) {
Uri uri = Uri.fromFile(new File(path));
InputStream in = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
in = getContentResolver().openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);
Bitmap b = null;
in = getContentResolver().openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
o = new BitmapFactory.Options();
o.inSampleSize = scale;
b = BitmapFactory.decodeStream(in, null, o);
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
(int) y, true);
b.recycle();
b = scaledBitmap;
System.gc();
} else {
b = BitmapFactory.decodeStream(in);
}
in.close();
Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " +
b.getHeight());
return b;
} catch (IOException e) {
Log.e("", e.getMessage(), e);
return null;
}
}
I hope it helps!
When I want parse full image without resize but must be resize in requirement of code.
When I set
options.inSampleSize = 1;
Then decode of image show black. But I want full image
that means
options.inSampleSize = 1;
and also
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
But I unable to make this.
My code below :
public class MainActivity extends Activity {
public String imageName, imagePath;
public Context context;
public static final String TAG = "MainActivity";
protected static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 0;
public File dir;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dir = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/" + "Test_Folder");
if (dir.exists()) {
Log.i(TAG, "folder already exist");
} else {
if (dir.mkdirs()) {
Log.i(TAG, "folder make now");
}
}
SecureRandom random = new SecureRandom();
String randomName = new BigInteger(10, random).toString(4);
imageName = "myImage" + "" + randomName + ".JPEG";
File file = new File(dir, imageName);
imagePath = file.getAbsolutePath();
Uri outputFileUri = Uri.fromFile(file);
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(i, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 16;
options.inPurgeable = true;
Bitmap bm = BitmapFactory.decodeFile(imagePath,
options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);
// bitmap object
byte[] byteImage_photo = baos.toByteArray();
// generate base64 string of image
String imageRowData = Base64.encodeToString(byteImage_photo,
Base64.DEFAULT);
Log.i(TAG, "::image::" + imageRowData);
}
}
}
}
How to make sure full image encode without resize and decrease quality.
That means I want
options.inSampleSize = 1;
and also
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
It is possible? please help me.
im taking photo by using this method:
public void takePhoto () {
try {
Log.i(GlobalApplication.APP_LOG_NAMESPACE, "Trying to take photo");
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
} catch (Exception e) {
Log.e(GlobalApplication.APP_LOG_NAMESPACE, "takePhoto method cannot be processed", e);
e.printStackTrace();
}
}
On some devices i got always in onActivity result in image URI null (especially on Huawei devices).
I tried to find any working solution, but without luck.
Could please somebody tell me, how to solve this issue?
Here is onActivityResultMethod:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
try {
Log.i(GlobalApplication.APP_LOG_NAMESPACE, "Trying to process image");
GlobalApplication globalAppClass = ((GlobalApplication) getApplicationContext());
AppHelper helper = new AppHelper();
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
Uri imageUri = data.getData();
if(imageUri == null) {
Log.i(GlobalApplication.APP_LOG_NAMESPACE, "Image URI is null");
}
Bitmap bitmap;
Bitmap resizedBitmap;
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "DAMAGE_" + globalAppClass.getEanCode() + "_" + timeStamp + ".jpg";
String dirname = "smartt/"+globalAppClass.getEanCode();
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
resizedBitmap = helper.getResizedBitmap(bitmap, 768, 1024);
helper.createDirectoryAndSaveImage(resizedBitmap, imageFileName, dirname);
// place thumbnail into image view
//mImageView.setImageBitmap(imageBitmap);
TextView photoCountTv = (TextView)findViewById(R.id.damageReportTakenPhotosCountTv);
photoCountTv.setText(R.string.foto_attached);
photoCountTv.setTextColor(getResources().getColor(R.color.green));
TextView dataPassingTv = (TextView)findViewById(R.id.damageReportPassingTitle);
dataPassingTv.setText(R.string.data_passing);
dataPassingTv.setTextColor(getResources().getColor(R.color.green));
} catch (FileNotFoundException e) {
Log.e(GlobalApplication.APP_LOG_NAMESPACE, "onActivityResult method cannot be processed, file not found", e);
e.printStackTrace();
} catch (IOException e) {
Log.e(GlobalApplication.APP_LOG_NAMESPACE, "onActivityResult method cannot be processed, IOE Exception", e);
e.printStackTrace();
} catch (Exception e) {
Log.e(GlobalApplication.APP_LOG_NAMESPACE, "onActivityResult method cannot be processed, Exception", e);
e.printStackTrace();
}
}
}
Thanks for any advice
i know this question is older, but i think many people have a problem with that. As #CommonsWare stated out you have to provide your own URI like this:
photoFile = getOutputMediaFile();
// Continue only if the File was successfully created
if (photoFile != null) {
String fileName = photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
with a file like this:
public File getOutputMediaFile() {
// 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),
"Shaufel");
// 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()) {
// base.saveValidationError("MyCameraApp: failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp
+ ".jpg");
return mediaFile;
}
just safe in your application the fileName (perhaps also onSaveInstanceState())
in onActivityResult i load the bitmap like this
public Bitmap decodeSampledBitmapFromResource(Resources res, File file, int reqWidth,
int reqHeight) throws IOException {
FileInputStream ino = new FileInputStream(new File(fileName));
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(ino.getFD(), null, options);
ino.close();
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(fileName, options);
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
this.reqHeight = reqHeight;
this.reqWidth = reqWidth;
// Raw height and width of image
this.height = options.outHeight;
this.width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power
// of 2 and keeps both
// height and width larger than the requested height and
// width.
while ((halfHeight / inSampleSize) > reqHeight
|| (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
I was practicing around with the Camera API for which I did the following:
a. Setup a directory for the image captured (for startActivityForResult)
b. Setup the Bitmap so that the image could be shown once saved in the app itself.
Here's the code for the following:
Setting up the directory.
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, "Oops! Failed create "
+ 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
+ "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
Global variables in the application
// Activity request codes
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
// directory name to store the captured images
private static final String IMAGE_DIRECTORY_NAME = "my_camera_app";
private Uri fileUri;
// Views
ImageView photo;
Button camera;
Camera implementation logic
// Use camera function
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);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Successfully captured the image
// display in imageview
previewImage();
} else {
// failed to capture image
Toast.makeText(getApplicationContext(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
.show();
}
}
}
private void previewImage() {
try {
// Bitmap factory
BitmapFactory.Options options = new BitmapFactory.Options();
// Downsizing image as it throws OutOfMemory exception for larger
// images
options.inSampleSize = 3;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
photo.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
The problem I am having is that ... for some of the devices that I tested the app, the app shows a blank preview of the image shot while in others the app works completely well.
Why am I getting a blank feedback ? and in some of the cases, when an image is saved, the user is not directed to my app, instead the user is stuck in the camera app.
Please do help.
I had the same problem and solved it by changing the rendering of the view to software
ImageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
At least for Kitkat 4.4.2 on a Galaxy S4, with a relative layout, I had to call invalidate() on the ImageView that i just setImageBitmap on. If i didn't, i got the blank screen. After adding the invalidate() after setImageBitmap(), then I got the image.
try loading bitmap efficiently:
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
//BitmapFactory.Options optionss = new BitmapFactory.Options();
//optionss.inPreferredConfig = Bitmap.Config.RGB_565;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeFile(path,options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;}
Actually it is setting but it doesnt appear for some reason.
profileImageView.post(new Runnable() {
#Override
public void run() {
profileImageView.setImageBitmap(bm);
}
});
This works for me.
One way I got around this problem was when setting the FileUri, I stored the Uri using SharedPreferences. So in my code:
public void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = FileHelper.getOutputMediaFileUri();
// Store uri to SharedPreferences
pref.setImageUri(fileUri.toString());
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
In my onActivityResult callback:
if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK) {
// If user is taking photo then only call the SharedPreferences
// If user is selecting photo from gallery, we can use the Intent data
fileUri = Uri.parse(pref.getImageUri());
if (fileUri.getPath().toString().length() < 1) {
Toast.makeText(getApplicationContext(),
"Sorry something went wrong ... Please try again",
Toast.LENGTH_LONG).show();
} else {
String path = fileUri.getPath().toString();
db_img_path = path;
imageholder.setVisibility(View.VISIBLE);
Bitmap bitmap = PathtoImage.previewImage(path);
imagepreview.setImageBitmap(bitmap);
}
}
Bonus :)
In my previewImage method, I have made adjustments for orientation, the code looks like this :
public static Bitmap previewImage(String path) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
final Bitmap bitmap = BitmapFactory.decodeFile(path, options);
// Providing adjustment so that the image is shown in the correct orientation
Matrix adjustment = adjustOrientation(path);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), adjustment, true);
return resizedBitmap;
}
In this method I call another method adjustOrientation which gives me the Matrix fix to the image.
// Adjustment for orientation of images
public static Matrix adjustOrientation(String path) {
Matrix matrix = new Matrix();
try {
ExifInterface exifReader = new ExifInterface(path);
int orientation = exifReader.getAttributeInt(
ExifInterface.TAG_ORIENTATION, -1);
if (orientation == ExifInterface.ORIENTATION_NORMAL) {
// do nothing
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
matrix.postRotate(90);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
matrix.postRotate(180);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
matrix.postRotate(270);
}
} catch (IOException e) {
e.printStackTrace();
}
return matrix;
}
This is my implementation for the issue, if anyone has a better implementation to this, please do post :)
In my case, it's fixed by adding android:layerType="software" in XML.
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layerType="software"
android:src="#drawable/placeholder"/>
Hopefully this will help you too!
I am using this code (from www.internetria.com) to take a photo and upload to a server:
onCreate:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri output = Uri.fromFile(new File(foto));
intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
startActivityForResult(intent, TAKE_PICTURE);
onActivityResult:
ImageView iv = (ImageView) findViewById(R.id.imageView1);
iv.setImageBitmap(BitmapFactory.decodeFile(foto));
File file = new File(foto);
if (file.exists()) {
UploaderFoto nuevaTarea = new UploaderFoto();
nuevaTarea.execute(foto);
}
else
Toast.makeText(getApplicationContext(), "No se ha realizado la foto", Toast.LENGTH_SHORT).show();
UploaderFoto:
ProgressDialog pDialog;
String miFoto = "";
#Override
protected Void doInBackground(String... params) {
miFoto = params[0];
try {
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://servidor.com/up.php");
File file = new File(miFoto);
MultipartEntity mpEntity = new MultipartEntity();
ContentBody foto = new FileBody(file, "image/jpeg");
mpEntity.addPart("fotoUp", foto);
httppost.setEntity(mpEntity);
httpclient.execute(httppost);
httpclient.getConnectionManager().shutdown();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
And I want to compress the image, because the size is too big.
I don't know how to add bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); to my app
Take a look over here: ByteArrayOutputStream to a FileBody
Something along these lines should work:
replace
File file = new File(miFoto);
ContentBody foto = new FileBody(file, "image/jpeg");
with
Bitmap bmp = BitmapFactory.decodeFile(miFoto)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 70, bos);
InputStream in = new ByteArrayInputStream(bos.toByteArray());
ContentBody foto = new InputStreamBody(in, "image/jpeg", "filename");
If file size is still an issue you may want to scale the picture in addition to compressing it.
Convert image to Google WebP format it will save you lots of bytes see the following two articles you can also convert webP into JPG/PNG/GIF whatever you want on server side.
Java Wrapper of Google WebP API
How to check out Google WebP library and use it in Android as native library
First, you need to get pixels from Bitmap.
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
int bytes = bitmap.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
byte[] pixels = buffer.array();
Then, you can get WebP byte array.
int stride = bytes / height;
int quality = 100;
byte[] encoded = libwebp.WebPEncodeRGBA(pixels, width, height, stride, quality);
Test.png (Size: 106KB)
Test.webp(Size: 48KB)
Using okhttp I upload like this:
MediaType MEDIA_TYPE_PNG
= MediaType.parse("image/jpeg");
//Compress Image
Bitmap bmp = BitmapFactory.decodeFile(fileToUpload.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 70, bos);
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("photo", fileToUpload.getName(), RequestBody.create(MEDIA_TYPE_PNG, bos.toByteArray()))
.build();
request = new Request.Builder()
.url(urlToUploadTo)
.post(requestBody)
.build();
try {
response = client.newCall(request).execute();
if (response != null) {
if (response.isSuccessful()) {
responseResult = response.body().string();
}
}
} catch (IOException e) {
e.printStackTrace();
}
Have a look at the compressImage() method:
public class MainActivity extends Activity {
private Uri fileUri;
private ImageView img_forCompress;
public static final int MEDIA_TYPE_IMAGE = 1;
private static final int CAMERA_REQUEST = 1888;
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
private static final String IMAGE_DIRECTORY_NAME = "Ibook";
static File mediaFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_forCompress = (ImageView) findViewById(R.id.img_forCompress);
img_forCompress.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent,
CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
});
}
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
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, "Oops! Failed create "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
Log.e("path", "media file:-" + mediaFile);
return mediaFile;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Log.e("path", "" + mediaFile.toString());
String filename = mediaFile.toString();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
compressImage(bitmap);
}
private void compressImage(Bitmap photo) {
// TODO Auto-generated method stub
int imageWidth = photo.getWidth();
int imageHeight = photo.getHeight();
long length = mediaFile.length();
int newHeight = 0;
int newWidth = 0;
Toast.makeText(MainActivity.this, "oldwidth="+imageWidth+",oldHeight="+imageHeight,Toast.LENGTH_LONG).show();
Log.e("Old Image gheight and width---------", imageWidth + "-------"
+ imageHeight + " and Size is -- " + length);
if (imageHeight > 1500 || imageWidth > 1500) {
if (imageHeight > imageWidth) {
Log.e("height is more", "true");
newHeight = 1200;
newWidth = (newHeight * imageWidth / imageHeight);
}
if (imageWidth > imageHeight) {
Log.e("width is more", "true");
newWidth = 1200;
newHeight = (newWidth * imageHeight / imageWidth);
}
}
Toast.makeText(MainActivity.this, "newwidth="+newWidth+",newHeight="+newHeight,Toast.LENGTH_LONG).show();
Log.e("new Image gheight and width---------", newHeight + "-------"