Hi Guys My application quits just after the image is saved, I cannot see why, Please help?
This is the button pressed method, after the picture is taken I press save, The image gets saved where it needs to be saved but the application just quits after I press save, It does not say "Not Responding", it just quits
cam.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
leakerID = leakId.getText().toString();
String direc = "/e3softData/DCIM/";
String fileName = leakerID+".jpg";
// get the path to sdcard
File sdcard = Environment.getExternalStorageDirectory();
// to this path add a new directory path
File dir = new File(sdcard.getAbsolutePath() + direc);
// create this directory if not already created
dir.mkdir();
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
File file = new File(dir, fileName);
String f = file.toString();
Uri uriSavedImage = Uri.fromFile(new File(f));
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(intent, 0);
}
});
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File dir = new File(Environment.getExternalStorageDirectory() + "/e3softData/DCIM/");
if (!dir.exists()) {
dir.mkdir();
}
String fileName = leakerID+".jpg";
output = new File(dir.getAbsolutePath(), fileName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(output));
startActivityForResult(intent, 0);
}
I just want to save a picture in my Imagefolder in my phone.
I have got 2 examples which I tried.
1. Example
My app crashes when I activate the onClick Method:
public void onClick(View arg0) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 1337);
}});
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if( requestCode == 1337)
{
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
}
else
{
Toast.makeText(AndroidCamera.this, "Picture NOt taken", Toast.LENGTH_LONG);
}
super.onActivityResult(requestCode, resultCode, data);
}
2. Example
Before I saved my taken Picture with Uri. But it saved my picture in a folder, which I can only access on my PC or with a FileApp. I donĀ“t know how I can change the Path direction with Uri to my existing default image folder in my phone.
Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());
This is how I manage with saving images to specified imagefolder
When starting camera intent I define path and directory, where my image should be saved, and pass this as intetn extra when starting camera:
private void startCameraIntent() {
//create file path
final String photoStorePath = getProductPhotoDirectory().getAbsolutePath();
//create file uri
final Uri fileUri = getPhotoFileUri(photoStorePath);
//create camera intent
final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//put file ure to intetn - this will tell camera where to save file with image
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start activity
startActivityForResult(cameraIntent, REQUEST_CODE_PHOTO_FROM_CAMERA);
//start image scanne to add photo to gallery
addProductPhotoToGallery(fileUri);
}
And here are some of helper methods used in code above
private File getProductPhotoDirectory() {
//get directory where file should be stored
return new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES),
"myPhotoDir");
}
private Uri getPhotoFileUri(final String photoStorePath) {
//timestamp used in file name
final String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.US).format(new Date());
// file uri with timestamp
final Uri fileUri = Uri.fromFile(new java.io.File(photoStorePath
+ java.io.File.separator + "IMG_" + timestamp + ".jpg"));
return fileUri;
}
private void addProductPhotoToGallery(Uri photoUri) {
//create media scanner intetnt
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//set uri to scan
mediaScanIntent.setData(photoUri);
//start media scanner to discover new photo and display it in gallery
this.sendBroadcast(mediaScanIntent);
}
I am a beginner in android programming.
Here is a code to take a image and save it in a folder in sdcard. The image is saved in gallery but it is not saved in the location where i want to. Please help...
public class CameraActivity extends Activity {
/** Called when the activity is first created. */
Button button1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1=(Button)findViewById(R.id.button1);
}
public void send(View v)
{
Intent imageIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(
Environment.getExternalStorageDirectory(),
"MyImages");
imagesFolder.mkdirs(); //
File image = new File(imagesFolder, "image_001.jpg");
Uri uriSavedImage = Uri.fromFile(image);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent,0);
}
}
Finally I got the solution, the modified code is:
File image = new File("/sdcard/picture.jpg");
Uri uriSavedImage = Uri.fromFile(image);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
// start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
You should append a / to your MyImages string. eg,
new File(Environment.getExternalStorageDirectory() + "/MyImages/");
That should create a reference to a directory, not a file as it currently is.
I am creating an application in which I want to capture a image and then I want to send that image in the email as a attachment.
I am opening a camera using android.provider.MediaStore.ACTION_IMAGE_CAPTURE intent action and I am passing the Uri of the file as a parameter EXTRA_OUTPUT to get the image back to the file. This is working perfectly and I am able to get the captured image if I use the external storage uri as a EXTRA_OUTPUT but if I use the data folder uri it is not working and the camera is not closing and its all buttons are not working.
Here is my code for get the result in the external storage directory
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);
And this code is for get the image in the data folder
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = getFilesDir();
out = new File(out, MyPharmacyOptions.PRESCRIPTION_IMAGE_NAME);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);
I knew that the data folder is not accessible to third application so may be this causes an issue so I have create one content provider to share the file.
Here is my content provide class
public class MyContentProvider extends ContentProvider {
private static final String Tag = RingtonContentProvider.class.getName();
public static final Uri CONTENT_URI = Uri
.parse("content://x.y.z/");
private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();
static {
MIME_TYPES.put(".mp3", "audio/mp3");
MIME_TYPES.put(".wav", "audio/mp3");
MIME_TYPES.put(".jpg", "image/jpeg");
}
#Override
public boolean onCreate() {
return true;
}
#Override
public String getType(Uri uri) {
String path = uri.toString();
for (String extension : MIME_TYPES.keySet()) {
if (path.endsWith(extension)) {
return (MIME_TYPES.get(extension));
}
}
return (null);
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
File f = new File(getContext().getFilesDir(), uri.getPath());
if (f.exists()) {
return (ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY));
}
throw new FileNotFoundException(uri.getPath());
}
#Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
throw new RuntimeException("Operation not supported");
}
#Override
public Uri insert(Uri uri, ContentValues initialValues) {
File file = new File(getContext().getFilesDir(), uri.getPath());
if(file.exists()) file.delete();
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Uri.fromFile(file);
}
#Override
public int update(Uri uri, ContentValues values, String where,
String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
#Override
public int delete(Uri uri, String where, String[] whereArgs) {
File f = new File(getContext().getFilesDir(), "image1.jpg");
if(f.exists()) f.delete();
f = new File(getContext().getFilesDir(), "image2.jpg");
if(f.exists()) f.delete();
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
}
}
So to use this content provide I am using following code to pass the uri to the camera activity
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = MyContentProvider.CONTENT_URI;
uri = Uri.withAppendedPath(uri, imagename);
getContentResolver().insert(uri, null);
getContentResolver().notifyChange(RingtonContentProvider.CONTENT_URI, null);
Log.d(Tag, uri.toString());
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(i, CAMERA_RESULT);
Now if I pass the url other then external storage directory the camera is opening but it is not closing in emulator but in device the camera is going to closed but I am not getting the result.
I have declared this content provide in the manifest file
<provider
android:name=".contentproviders.MyContentProvider"
android:authorities="x.y.z" />
Also I have given the permission to write the external storage and also for use the camera.
I am able to capture the image using the external storage but I want to store the image in the data directory instead of external storage because if the external storage in not available I want to capture the image and want to send mail.
If I create content provide then I can also share my image to the email application.
If we not provide the extras with the camera intent it will return the image as a byte[] in the activity result as a data extra but this is for the purpose of the thumbnail so I can't get the high resolution image using this way.
There are two ways to solve this problem.
1. Save bitmap which you received from onActivityResult method
You can start camera through intent to capture photo using below code
Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
After capture photo, you will get bitmap in onActivityResult method
if (requestCode == CAMERA_REQUEST) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
}
Now you can simply save this bitmap to internal storage
Note: Here bitmap object consists of thumb image, it will not have a full resolution image
2. Save bitmap directly to internal storage using content provider
Here we will create content provider class to allow permission of local storage directory to camera activity
Sample provider example as per below
public class MyFileContentProvider extends ContentProvider {
public static final Uri CONTENT_URI = Uri.parse
("content://com.example.camerademo/");
private static final HashMap<String, String> MIME_TYPES =
new HashMap<String, String>();
static {
MIME_TYPES.put(".jpg", "image/jpeg");
MIME_TYPES.put(".jpeg", "image/jpeg");
}
#Override
public boolean onCreate() {
try {
File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
if(!mFile.exists()) {
mFile.createNewFile();
}
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
return (true);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#Override
public String getType(Uri uri) {
String path = uri.toString();
for (String extension : MIME_TYPES.keySet()) {
if (path.endsWith(extension)) {
return (MIME_TYPES.get(extension));
}
}
return (null);
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
File f = new File(getContext().getFilesDir(), "newImage.jpg");
if (f.exists()) {
return (ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_WRITE));
}
throw new FileNotFoundException(uri.getPath());
}
}
After that you can simply use the URI to pass to camera activity using the below code
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);
If you don't want to create your own provider then you can use FileProvider from support-library-v4. For detailed help you can look into this post
Best solution I found is: FileProvider (needs support-library-v4)
It uses the internal storage!
https://developer.android.com/reference/android/support/v4/content/FileProvider.html
Define your FileProvider in Manifest in Application element:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="your.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/image_path" />
</provider>
Add permissions in manifest root element:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
Define your image paths in for example res/xml/image_path.xml:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="captured_image" path="your/path/"/>
</paths>
Java:
private static final int IMAGE_REQUEST_CODE = 1;
// your authority, must be the same as in your manifest file
private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider";
4.1 capture intent:
File path = new File(activity.getFilesDir(), "your/path");
if (!path.exists()) path.mkdirs();
File image = new File(path, "image.jpg");
Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, IMAGE_REQUEST_CODE);
4.2 onActivityResult():
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == IMAGE_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File path = new File(getFilesDir(), "your/path");
if (!path.exists()) path.mkdirs();
File imageFile = new File(path, "image.jpg");
// use imageFile to open your image
}
}
super.onActivityResult(requestCode, resultCode, intent);
}
Intent to call to capture photo,
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
Then Take Bitmap in ActivityResult
if (requestCode == CAMERA_REQUEST) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
}
Then Write that Into Internal Memory, see this
// The openfileOutput() method creates a file on the phone/internal storage in the context of your application
final FileOutputStream fos = openFileOutput("my_new_image.jpg", Context.MODE_PRIVATE);
// Use the compress method on the BitMap object to write image to the OutputStream
bm.compress(CompressFormat.JPEG, 90, fos);
Then next time to read that file,
Bitmap bitmap = BitmapFactory.decodeFile(file);
At first save came photo in your external storage and try it -
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.imageView = (ImageView)this.findViewById(R.id.imageView1);
Button photoButton = (Button) this.findViewById(R.id.button1);
photoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
Bitmap bmp = intent.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray(); // convert camera photo to byte array
// save it in your external storage.
FileOutputStream fo = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/_camera.png"));
fo.write(byteArray);
fo.flush();
fo.close();
}
}
Next target -
File cameraFile = new File(Environment.getExternalStorageDirectory() + "/_camera.png");
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_SEND)
.setType("image/jpg")
.putExtra(Intent.EXTRA_SUBJECT, "Subject")
.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(cameraFile))
.putExtra(Intent.EXTRA_TEXT, textBody), "Send your message using"), Constant.EMAIL);
You can also do this without needing a content provider since you will need the sd card to open the camera image capture intent anyway. You can of course hack around the presence of the sd card but not with the camera intent capture....So you are checking for external storage but need it at this point.... FYI you should also check out a crop library like crop-image instead of using native, as it is not well supported across devices.
File mediaStorageDir;
String photoFileName = "photo.jpg";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// page = getArguments().getInt("someInt", 0);
// title = getArguments().getString("someTitle");
// Get safe storage directory for photos
mediaStorageDir = new File(
Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
APP_TAG);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.isDirectory());
Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.getPath());
Log.d(APP_TAG,
"Directory exists: "
+ Environment.getExternalStorageState());
Log.d(APP_TAG, "failed to create directory");
}
}
in your 'take the pic' code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri(photoFileName));
...
public Uri getPhotoFileUri(String fileName) {
return Uri.fromFile(new File(mediaStorageDir.getPath() + File.separator
+ fileName));
}
After researching this bug for some time, I have noticed that the activity that called the camera intent is only restarted when the phone is running out of memory.
so because the activity is restarted, the object holding the path or Uri to the captured image is refreshed (nulled)
so I would suggest you catch/ detect the null object in the onActivityResult, and prompt the user to free up space on their device or restart their phone for a quick temporary fix.
Theres a problem I can't seem to fix:
In my OnCreate in the CameraActivity, I delete the picture first if it's there. If there is a situation where this is done, the picture file is created but the picture is blank. (so only creates the picture successfully if the file isn't there in the first place). How do I delete the file and create it successfully?
My CameraActivity is defined as follows:
public class CameraActivity extends Activity
{
final int PICTURE_ACTIVITY = 1;
#Override
public void onCreate(Bundle savedInstanceState)
{
Intent h = getIntent();
String filename = h.getStringExtra("string") + ".jpg";
String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/" + getString(R.string.app_name)+ "/";
File newdir = new File(dir);
try{
newdir.mkdirs();
}
catch(Exception e){}
String file = dir + filename;
File newfile = new File(file);
boolean deleted = newfile.delete();
try {
System.out.println("creating:");
newfile.createNewFile();
} catch (IOException e) {}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
super.onCreate(savedInstanceState);
startActivityForResult(cameraIntent, PICTURE_ACTIVITY);
}
}
I realised the reason it wasn't saving sometimes was because I was taking the SD card out of the phone before it had the chance to save.