I'm building an Android app that takes a picture and then immediately goes to a crop screen. I couldn't figure out how to pass the image without downgrading it (i.e. if i was to put it in a Bundle), so I just decided to save the image and pull it back off the card.
Right now when I'm trying to get the image back in the new crop_view, which comes right after the camera_view, the app throws a Null Pointer Exception on the line indicated in the code below. The image is actually being set at Pictures/MyApp/IMG_APP.jpg where "Pictures" is my default picture directory.
public Bitmap getImage() {
Bitmap toReturn = null;
File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
ImageView IV = (ImageView) findViewById(R.id.crop_view);
toReturn = BitmapFactory.decodeFile(root+"/MyApp/IMG_APP.jpg");
IV.setImageBitmap(toReturn);
return toReturn;// TODO Fix this line. It is breaking here with a null pointer exception.
}
Below this is the code where the picture is being saved. I have confirmed that it is being saved by checking on the actual sd card in another app.
void onPictureJpeg(byte[] bitmapdata, Camera camera) {
int i = bitmapdata.length;
Log.d(TAG, String.format("bytes = %d", i));
File f = IMGP_Photo_Handler.generateTimeStampPhotoFile();
try {
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(f));
outputStream.write(bitmapdata);
outputStream.flush();
outputStream.close();
exceptionCaught = false;
} catch (Exception e) {
Log.e(TAG, "Error accessing photo output file:" + e.getMessage());
Toast
.makeText(IMGP_Camera.this, "Cannot save file. \nPlease mount an external SD Card", Toast.LENGTH_LONG)
.show();
exceptionCaught = true;// To get this to not start the next intent if the file save doesn't work.
}
if(!exceptionCaught){
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
Intent intent = new Intent();
intent.setClass(IMGP_Camera.this, IMGP_Crop.class);
intent.putExtra("po","3265695");
startActivity(intent);
}
finish();
}
And then finally my photo_handler:
public static Uri photoFileUri = null;
public static File getPhotoDirectory() {
File outputDir = null;
String externalStorageState = Environment.getExternalStorageState();
if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
File pictureDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
outputDir = new File(pictureDir, "MyApp");
if(!outputDir.exists()) {
if(!outputDir.mkdirs()) {
String message = "Failed to create directory:" + outputDir.getAbsolutePath();
Log.e(TAG, message);
outputDir = null;
}
}
}
return outputDir;
}
public static File generateTimeStampPhotoFile() {
File photoFile = null;
File outputDir = getPhotoDirectory();
if (outputDir != null) {
String photoFileName = "IMG_APP.jpg";
photoFile = new File(outputDir, photoFileName);
}
return photoFile;
}
public static Uri generateTimeStampPhotoFileUri() {
photoFileUri = null;
File photoFile = generateTimeStampPhotoFile() ;
if (photoFile != null) {
photoFileUri = Uri.fromFile(photoFile);
}
return photoFileUri;
}
public static Uri getFile(){
return photoFileUri;
}
I fixed this by passing the path to the photo and uri in an extra:
String photoFileName = "IMG_TQL.jpg";
photoFile = new File(outputDir, photoFileName);
photoFilePath = photoFile.getAbsolutePath();
Intent intent = new Intent();
intent.setClass(IMGP_Camera.this, IMGP_Crop.class);
intent.putExtra("path", path);
intent.putExtra("uri", uri);
startActivity(intent);
Related
The user clicks image from his phone (using camera 2 api). I am storing it on users device using following function. I am not using bitmap.
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// create the file where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
// Error message
Toast.makeText(this, "Error occured while creating the file", Toast.LENGTH_SHORT).show();
}
//Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this, "com.valuefintech.android.fileprovider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
private File createImageFile() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timestamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName,
".jpg",
storageDir
);
//save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
and then it displays the image on imageview using following code
if(requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
File f = new File(currentPhotoPath);
idImage.setImageURI(Uri.fromFile(f));
Log.d("tag", "Absolute url of image is " + Uri.fromFile(f));
byte[] b = new byte[(int) f.length()];
try {
FileInputStream fileInputStream = new FileInputStream(f);
fileInputStream.read(b);
for (int j = 0; j < b.length; j++) {
System.out.print((char) b[j]);
}
} catch (FileNotFoundException e) {
System.out.println("File Not Found.");
e.printStackTrace();
} catch (IOException e1) {
System.out.println("Error Reading The File.");
e1.printStackTrace();
}
byte[] byteFileArray = new byte[0];
try {
byteFileArray = FileUtils.readFileToByteArray(f);
} catch (IOException e) {
e.printStackTrace();
}
String base64String = "";
if (byteFileArray.length > 0) {
base64String = android.util.Base64.encodeToString(byteFileArray, android.util.Base64.NO_WRAP);
Log.i("File Base64 string", "IMAGE PARSE ==>" + base64String);
}
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
The problem is I am not able to convert the image into Base64 so that I can upload it to my server.
I am making an app which utilizes the camera, and has the ability to take a picture to use a simple image recognition API on it. I can use the gallery just fine to upload images, but straight from the camera is giving me massive issues. I have basically just copied the android dev documentation for most of the image creation, though may have needed to change some items here and there.
Here is the total code:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + "Image_for_Stack" + "_";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "Camera");
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = "file: " + image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
try {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.v(TAG, "IO Exception " + ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(getContextOfApplication(),
BuildConfig.APPLICATION_ID + ".provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, IMAGE_CAPTURE);
}
}
} catch (Exception e) {
Log.v(TAG, "Exception in dispatch " + e);
}
}
private void galleryAddPic() {
try {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
getContextOfApplication().sendBroadcast(mediaScanIntent);
} catch (Exception e) {
Log.v(TAG, "Exception " + e);
}
}
And in a separate class, this is called:
public static byte[] getByteArrayFromIntentData(#NonNull Context context, #NonNull Intent data) {
InputStream inStream = null;
Bitmap bitmap = null;
try {
inStream = context.getContentResolver().openInputStream(data.getData());
Log.v(TAG, "Instream works");
bitmap = BitmapFactory.decodeStream(inStream);
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
return outStream.toByteArray();
} catch (FileNotFoundException e) {
Log.v("FileOP Debug", "Exception " + e);
return null;
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException ignored) {
}
}
if (bitmap != null) {
bitmap.recycle();
}
}
}
Now, the image is created without issue. I can go to the emulator, look through the photo's app, and get:
.
However, I get this error when the code gets to giving inStream a value:
java.io.FileNotFoundException: /file:
/storage/emulated/0/DCIM/Camera/JPEG_Image_for_Stack_3248071614992872091.jpg
(No such file or directory) .
I don't exactly understand how this could be. The item clearly exists, and is saved on the phone. The app does request and is given the permission to write to external storage, and I have checked in the emulator permissions that it is given. Write also comes with read, so that shouldn't be an issue as far as I'm aware either.
Edit
To show where this code is being called from.
else if (requestCode == IMAGE_CAPTURE) {
galleryAddPic();
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
final ProgressDialog progress = new ProgressDialog(getContextOfApplication());
progress.setTitle("Loading");
progress.setMessage("Identify your flower..");
progress.setCancelable(false);
progress.show();
if (!CheckNetworkConnection.isInternetAvailable(getContextOfApplication())) {
progress.dismiss();
Toast.makeText(getContextOfApplication(),
"Internet connection unavailable.",
Toast.LENGTH_SHORT).show();
return;
}
client = ClarifaiClientGenerator.generate(API_KEY);
final byte[] imageBytes = FileOp.getByteArrayFromIntentData(getContextOfApplication(), mediaScanIntent);
As of right now, imageBytes will be null as the the FileNotFound exception is thrown on that method call.
You can try this code...
public class Images extends Activity
{
private Uri[] mUrls;
String[] mFiles=null;
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.images);
File images = Environment.getDataDirectory();
File[] imagelist = images.listFiles(new FilenameFilter(){
#override
public boolean accept(File dir, String name)
{
return ((name.endsWith(".jpg"))||(name.endsWith(".png"))
}
});
mFiles = new String[imagelist.length];
for(int i= 0 ; i< imagelist.length; i++)
{
mFiles[i] = imagelist[i].getAbsolutePath();
}
mUrls = new Uri[mFiles.length];
for(int i=0; i < mFiles.length; i++)
{
mUrls[i] = Uri.parse(mFiles[i]);
}
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this));
g.setFadingEdgeLength(40);
}
public class ImageAdapter extends BaseAdapter{
int mGalleryItemBackground;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount(){
return mUrls.length;
}
public Object getItem(int position){
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
ImageView i = new ImageView(mContext);
i.setImageURI(mUrls[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(260, 210));
return i;
}
private Context mContext;
}
}
Hi I am trying to make the images captured from my app inaccessible to the user. First I tried to save these images to internal storage which didnt work. Then I tried to hide them using "." infront of the folder name.I am not sure what the correct way to do this is. I also tried creating a file called .nomedia to bypass media scanner. I am very confused about the proper way to do this. Here's my code:
public String getImageUri(Context inContext, Bitmap inImage) {
/* *//* ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, ".title", null);
return Uri.parse(path);*//*
*/
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.myFolder");
file.mkdirs();
File mFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.nomedia");
mFile.mkdirs();
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
inImage.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
uri = MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return uri;
}
If I use file.mkdirs() I get filenotfoundexception. If i remove that line I get no errors but my uri is empty.
Does the above function return the file path as well? I need the file path and the uri later on. Any help is appreciated.
I guess you don't have to add another extension or something else just save them in external cache dir of your app and gallery app won't able to read your private directory until unless you notify about them.
so store your camera images here and no gallery app can detect it.
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
sample code
public static File createPictureFile(Context context) throws IOException {
Locale locale = Locale.getDefault();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", locale).format(new Date());
String fileName = "JPEG_" + timeStamp + "_";
// Store in normal camera directory
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(fileName, ".jpg", storageDir);
}
Save your image to internal storage instead. Other applications like MediaScanner or Gallery do not have permission to read from your own application memory. Sample code:
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"profile.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
Save the image with different extension.
For example: .jpg can be saved as .ttj.
Try this code. Set where you want to save the photo. Once you receive response on onActivityResult(), in the desired URI, you will get the photo.
public void captureImageFromCamera() {
fileUri = FileUtils.getInstance().getOutputMediaFile(null);
if(fileUri == null){
Utilities.displayToastMessage(ApplicationNekt.getContext(),
context.getString(R.string.unable_to_access_image));
return;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
Following function will give you desired path. Change it based on your project need.
public Uri getOutputMediaFile(String imageNameWithExtension) {
if (imageNameWithExtension == null)
imageNameWithExtension = "image_" + System.currentTimeMillis() + ".jpg";
String extPicDir = getExtDirPicturesPath();
if (!Utilities.isNullOrEmpty(extPicDir)) {
File mediaFile = new File(extPicDir, imageNameWithExtension);
return Uri.fromFile(mediaFile);
} else {
Log.d("tag", "getOutputMediaFile." +
"Empty external path received.");
return null;
}
}
public String getExtDirPicturesPath() {
File file = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (file != null)
return file.getPath();
else
Log.d("", "getExtDirPicturesPath failed. Storage state: "
+ Environment.getExternalStorageState());
return null;
}
To get the resultant photo.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK)
return;
switch (requestCode) {
case TAKE_PICTURE:
//fileuri variable has the path to your image.
break;
}
Hello!
I have a problem between the picture gallery and the mediastore in my android application when i use the camera intent in my fragment.
I checked on the android website to learn how to take a picture in a fragment and on some forums to know how to get the last picture took but the media store always give me the last-1th picture as if it was not able to find the last picture.
This is my code :
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.i(LOG_TAG,"ERRRRROR: "+ex.toString());
}
if (photoFile != null) {
mCurrentPhotoPath = "file:" +photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQ_CAMERA_PICTURE);
}
}
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mCurrentPhotoUri = contentUri;
mediaScanIntent.setData(contentUri);
getActivity().sendBroadcast(mediaScanIntent);
Log.d(LOG_TAG,"Photo SAVED");
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
mCurrentPhotoAbsolutePath = image.getAbsolutePath();
Log.i(LOG_TAG,"image path : "+image.getAbsolutePath());
return image;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_CAMERA_PICTURE)
{
if (resultCode == Activity.RESULT_OK)
{
galleryAddPic();
String filePath = getActivity().getPreferences(Context.MODE_PRIVATE).getString(TMP_PHOTO_FILE_LATEST_KEY, null);
handleCameraPicture(mCurrentPhotoUri.toString());
}
else
{
clearCurrentActionData();
}
}
}
private String getLastImagePath() {
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE
};
final Cursor cursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if (cursor.moveToFirst()) {
String imageLocation = cursor.getString(1);
File imageFile = new File(imageLocation);
Bitmap bm = BitmapFactory.decodeFile(imageLocation);
return imageFile.getPath().toString();
}
else{
return "";
}
}
The problem occurs HERE when i try to get the last image path
private void handleCameraPicture(String pictureFileUri)
{
_currentDataObjectBuilder.addParameter(DataObject.Parameter.IMAGE, String.valueOf(getFileCount()));
//create a copy of the file into the internal storage
final File pictureFile = new File(pictureFileUri);
Log.d(LOG_TAG,"picture file uri : "+pictureFileUri.toString());
FileOutputStream fos =null;
byte[] pictureData = new byte[0];
try
{
pictureData = compressImage(getLastImagePath());
fos = getActivity().openFileOutput(String.valueOf(getFileCount()), Context.MODE_PRIVATE);
fos.write(pictureData);
Log.i(LOG_TAG,"SETTING FILE OUTPUT STREAM");
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
try {
fos.close();
pictureFile.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
if (_currentAction.equals(Action.PICTURE_CAPTION) || _currentAction.equals(Action.ARCHIVE))
{
showMessageView();
}
else
{
sendCurrentActionData();
}
}
The handleCameraPicture function allows me to send the "last picture" to an external website.
I don't know what i do wrong so please help me! I'm gonna lose my mind else...
Thank you!
Thomas
Wouw!
I finally found the solution, actually the uri when i created the picture was different from the one when i tried to save the picture in the gallery so my cursor dropped a null pointer exception.
I updated my GalleryAddPic function to
private void galleryAddPic(Uri uri) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mCurrentPhotoUri = uri;
mediaScanIntent.setData(uri);
getActivity().sendBroadcast(mediaScanIntent);
Log.d(LOG_TAG,"Photo SAVED");
}
And now everything works fine!
I am building an android app that accesses the camera but i am wanting to save the image into a specific folder but i have no idea how to go about it. do i use a URI builder?
this is the code i have to get the image from the camera.
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
File photo = new File(Environment
.DIRECTORY_PICTURES), "pic.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
imageUri = Uri.fromFile(photo);
startActivityForResult(intent, TAKE_PICTURE);
You can create a file from your own directory like this:
private File openFileFromMyDirectory() {
File imageDirectory = null;
String storageState = Environment.getExternalStorageState();
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
imageDirectory = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "com.myapp.camera");
if (!imageDirectory.exists() && !imageDirectory.mkdirs()) {
imageDirectory = null;
} else {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
return new File(imageDirectory.getPath() +
File.separator + "IMG_" +
dateFormat.format(new Date()) + ".jpg");
}
}
return null;
}
Then get bitmap from uri:
Bitmap mCameraBitmap= MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
Finally save the bitmap into the file
private void saveImageToFile(File file) {
if (mCameraBitmap != null) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(file);
if (!mCameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream)) {
Toast.makeText(this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Saved image to: " + file.getPath(),
Toast.LENGTH_LONG).show();
}
outStream.close();
} catch (Exception e) {
Toast.makeText(this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
}
}
}