I have an ImageView with a share intent( which works great, brings up all the apps I can share the image with), however, I can not share the photo because it has no path on my phone. How do I go about saving the ImageView on my phone? Below is my code.
public void taptoshare(View v)
{
View content = findViewById(R.id.myimage);
content.setDrawingCacheEnabled(true);
Bitmap bitmap = content.getDrawingCache();
File file = new File("/DCIM/Camera/image.jpg");
try
{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri phototUri = Uri.parse("/DCIM/Camera/image.jpg");
shareIntent.setData(phototUri);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, phototUri);
startActivity(Intent.createChooser(shareIntent, "Share Via"));
}
}
UPDATE
Ok, so I figured it out. Now I have a new question, how would I go about saving this image to a new folder?
When saving and loading, you need to get the root path of the system, first. This is how I'd do it.
File root = Environment.getExternalStorageDirectory();
File cachePath = new File(root.getAbsolutePath() + "/DCIM/Camera/image.jpg");
I've come across a couple solutions which are not solving this problem.
Here is a solution that worked for me. One gotcha is you need to store the images in a shared or non app private location (http://developer.android.com/guide/topics/data/data-storage.html#InternalCache)
Many suggestions say to store in the Apps "private" cache location but this of course is not accessable via other external applications, including the generic Share File intent which is being utilised. When you try this, it will run but for example dropbox will tell you the file is no longer available.
/* STEP 1 - Save bitmap file locally using file save function below. */
localAbsoluteFilePath = saveImageLocally(bitmapImage);
/* STEP 2 - Share the non private Absolute file path to the share file intent */
if (localAbsoluteFilePath!=null && localAbsoluteFilePath!="") {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri phototUri = Uri.parse(localAbsoluteFilePath);
File file = new File(phototUri.getPath());
Log.d("file path: " +file.getPath(), TAG);
if(file.exists()) {
// file create success
} else {
// file create fail
}
shareIntent.setData(phototUri);
shareIntent.setType("image/png");
shareIntent.putExtra(Intent.EXTRA_STREAM, phototUri);
activity.startActivityForResult(Intent.createChooser(shareIntent, "Share Via"), Navigator.REQUEST_SHARE_ACTION);
}
/* SAVE IMAGE FUNCTION */
private String saveImageLocally(Bitmap _bitmap) {
File outputDir = Utils.getAlbumStorageDir(Environment.DIRECTORY_DOWNLOADS);
File outputFile = null;
try {
outputFile = File.createTempFile("tmp", ".png", outputDir);
} catch (IOException e1) {
// handle exception
}
try {
FileOutputStream out = new FileOutputStream(outputFile);
_bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (Exception e) {
// handle exception
}
return outputFile.getAbsolutePath();
}
/* STEP 3 - Handle Share File Intent result. Need to remote temporary file etc. */
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// deal with this with whatever constant you use. i have a navigator object to handle my navigation so it also holds all mys constants for intents
if (requestCode== Navigator.REQUEST_SHARE_ACTION) {
// delete temp file
File file = new File (localAbsoluteFilePath);
file.delete();
Toaster toast = new Toaster(activity);
toast.popBurntToast("Successfully shared");
}
}
/* UTILS */
public class Utils {
//...
public static File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file =
new File(Environment.getExternalStorageDirectory(), albumName);
if (!file.mkdirs()) {
Log.e(TAG, "Directory not created");
}
return file;
}
//...
}
I hope that helps someone.
Related
I am developing an application that captures photo and saves it in internal device folder named "photo".I need to load the photo from "photo" folder to imageview.There is only one photo present in the folder.How to do this?
Please help me.Thank you in advance.
Below is the code that I have tried which loads photo from folder only if name of photo is displayed.
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+ "/GeoPark/final_photo/20180504_002754.jpg";
File imgFile = new File(path);
if (imgFile.exists()) {
imageView.setImageBitmap(decodeFile(imgFile));
}
else
Toast.makeText(ViewActivity.this,"No Image File Present ",Toast.LENGTH_SHORT).show();
Try this method .. in below method give proper file path.
private void loadImageFromStorage(String path)
{
try {
File f=new File(path, "profile.jpg");
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
ImageView img=(ImageView)findViewById(R.id.imgPicker);
img.setImageBitmap(b);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
Second things ..
File file = ....
Uri uri = Uri.fromFile(file);
imageView.setImageURI(uri);
alos i hope you add below permission into android manifest file ..
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
You could simply do a search about this, guaranteed results.
Anyway, Glide will help you with that
EDIT :
Taking picture using camera:
private void dispatchTakePictureIntent(Context context) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile(context);
} catch (IOException ex) {
// Error occurred while creating the File
Snackbar.make(btn_open_camera, "Couldn't create a file for your picture!", Snackbar.LENGTH_LONG);
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(context,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, MY_PERMISSIONS_REQUEST_CAMERA);
}
}
}
private File createImageFile(Context context) throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getFilesDir();
Log.i(TAG, "StorageDir : " + storageDir);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
Log.i(TAG, "mCurrentPhotoPath : " + mCurrentPhotoPath);
return image;
}
Now you have the image path stored in mCurrentPhotoPath which is a String declared in current activity. As you said, you will need this in next activity, to do that you can take a look at this answer
I want to implement functionality for saving image in Downloads directory and after that offer to user to open this one in a directory (open directory in which user can find and open this image). But I've got one issue. Saving ends successfully, but when user clicks "OPEN" in snackbar and chooses app to perform this action another directory appears. It contains also "Downloads" directory as well, this Downloads directory does not contain saved images! It seems like in android we have two different "Downloads" directories.
Below is how i get path for save image:
private File getFileForImageSaving() {
String filename = getImageNameFromUrl(mImageUrl) + ".png";
File dest = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
filename);
int index = 1;
while (dest.exists()) {
filename = getImageNameFromUrl(mImageUrl) + "_" + index + ".png";
dest = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
filename);
index++;
}
return dest;
}
This is how i run activity for view "Download" directory and open files.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath());
intent.setDataAndType(uri, "image/png");
startActivity(Intent.createChooser(intent, "Open folder"));
This is how I save image. It is realy works, I've checked.
pri
vate void saveImageToFile() {
File dest = getFileForImageSaving();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
FileOutputStream out = null;
try {
dest.createNewFile();
out = new FileOutputStream(dest);
Bitmap bitmap = Glide.with(ArticleImageViewActivity.this)
.load(mImageUrl)
.asBitmap()
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
Utils.showInSnackBar(
ArticleImageViewActivity.this, getString(R.string.image_has_been_successfully_saved),
Snackbar.LENGTH_LONG,
onOpenImageInDirectoryListener,
getString(R.string.open_image_in_directory));
} catch (Exception e) {
Utils.showInSnackBar(ArticleImageViewActivity.this,
getString(R.string.error_occurred_during_saving_image),
Snackbar.LENGTH_SHORT, null, null);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}.execute();
}
I partially resolve my problem by using Intent.ACTION_VIEW instead of Intent.ACTION_GET_CONTENT and " / " mime type instead of "image/png". But only partially because in this case user will be offered to choose a wide range of applications, but not only applications like filemanagers.
use MediaScannerConnection.scanFile to scan the file after saving. if you don't many/most galleries wont show your file.
https://developer.android.com/reference/android/media/MediaScannerConnection.html
i wanted to add file with specific path like that to view it as in image .. worked fine
File imgFile = new File("/storage/emulated/0/DSC_0008.JPG");
if (imgFile.exists()) {
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageView);
myImage.setImageBitmap(myBitmap);
BUT
that is not where i find my photo .. if i tried opening it manually and not from the studio
any idea how this work .. and how do i know the path that should i use to get any photo on my android
The "/storage/emulated/0/" folder does not really exist.
It's what might be called a "symbolic link", or, in simpler terms, a reference to where the real data is stored. You'll need to find the actual physical location on your device where it is stored.
Since it's in /storage/emulated/0/DSC_0008.JPG, it's probably located in /Internal Storage/DSC_0008.JPG/. Please note that that this folder probably only contains "DSC_0008.JPG", which are very small versions of the real files.
It's possible your real files are gone forever if your SD card is irrecoverable.
As Hiren stated, you'll need a file explorer to see your directory. If you're rooted I highly suggest root explorer, otherwise ES File Explorer is a good choice.
You can user file chooser for get image path
private void chooserImage(){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 1888);
}
Then override a method called onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == getActivity().RESULT_OK && requestCode==1888){
Uri imageUri = data.getData();
String path = imageUri.getPath().toString();
File imgFile = new File(new URI(path));
//Then Here user your code
if (imgFile.exists()) {
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageView);
myImage.setImageBitmap(myBitmap);
}
}
}
Just Call on any event chooserImage(); to choose file and show as ImageView
You need one more step: set permission to read SD card. Add this in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Judging by the filename, DSC_0008.JPG, I'm assuming it was made with the Camera app. If that's the case your file should be in /sdcard/DCIM/Camera/
try this
File imgFile = getOutputFile("myfileName", "imagesSubFolder");
public static File getOutputFile(String fileName, String subFolderName) {
File mediaStorageDir;
if (subFolderName == null) {
mediaStorageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), Path.PHOTO_DIRECTORY);
} else {
mediaStorageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), Path.PHOTO_DIRECTORY + File.separator + subFolderName);
}
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
} else {
try {
if (subFolderName != null) {
File noMediaFile = new File(mediaStorageDir, ".nomedia");
noMediaFile.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return new File(mediaStorageDir.getPath() + File.separator + fileName);
}
good luck
I've seen several exemples but still don't get why, when I'm editing the mail I see the .xml attached but when I receive ther's no attachment!
Here is my code
File f = new File("data/data/xxx/files/xxx.xml");
Boolean b1 = f.exists();
Boolean b2 = f.canRead();
if (b1 && b2) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_EMAIL, "");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" +
f.getAbsolutePath()));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "XXX");
sendIntent.putExtra(Intent.EXTRA_TEXT, R.string.mail_body);
startActivity(Intent.createChooser(sendIntent, "Email:"));
} else {
...
Ah, only a detail...when I choose the app to send there is no subject or body, even if I wrote putExtra(Intent.EXTRA_SUBJECT) and putExtra(Intent.EXTRA_TEXT), but that's a detail...
Edit: I just debuged my intent: it says "NOT CACHED" in value of the stream, how to solve it?
You can't attach a file from internal storage directly for some security purpose, hence first you have to copy that file from internal to external directory and then mail after that if you want you can delete that file from external storage in onActivityResult() method.
Here's a code :
private File copyFileToExternal(String fileName) {
File file = null;
String newPath = Environment.getExternalStorageState()+"/folderName/";
try {
File f = new File(newPath);
f.mkdirs();
FileInputStream fin = openFileInput(fileName);
FileOutputStream fos = new FileOutputStream(newPath + fileName);
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = fin.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fin.close();
fos.close();
file = new File(newPath + fileName);
if (file.exists())
return file;
} catch (Exception e) {
}
return null;
}
Method to Email:
private void sendEmail(String email) {
File file = new File(Environment.getExternalStorageState()+"/folderName/" + fileName+ ".xml");
Uri path = Uri.fromFile(file);
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
String to[] = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, message);
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."),
1222);
}
and then
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1222) {
File file = new File(Environment.getExternalStorageState()+"/folderName/" + fileName+ ".xml");
file.delete();
}
}
Call this method like this:
copyFileToExternal(filename + ".xml");
sendEmail(EmailId);
I've seen several exemples but still don't get why, when I'm editing the mail I see the .xml attached but when I receive ther's no attachment!
First, third-party apps cannot read internal storage of your app.
Second, that might not be the right path to internal storage of your app. Never hardcode paths. Your app will fail for secondary accounts and restricted profiles on Android 4.2 tablets, for example. Always use a method, like getFilesDir(), to get at your portion of internal storage.
You will need to either copy your file to external storage, or better yet, use FileProvider to serve up your file from internal storage via a content:// Uri.
in main activity i have a button takeApic that will start the intent to access the camera then on onActivityResult i have passed the bitmap to other activity(ShowActivity)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST) {
// 2
Bitmap show_img = (Bitmap) data.getExtras().get("data");
Intent mIntent = new Intent(MainActivity.this,ShowActivity.class);
mIntent.putExtra("BitmapImage", show_img);
startActivity(mIntent);
}
then ShowActivity set the taken image (i have received through intent) in an imageview
Intent mIntent = getIntent();
/** retrieve the string extra passed */
Bitmap our_img = (Bitmap) mIntent.getParcelableExtra("BitmapImage");
mImage.setImageBitmap(our_img);
when the button Save is pressed on ShowActivity is should save the image here is my code
FileOutputStream output;
File filepath = Environment.getExternalStorageDirectory();
// Create a new folder AndroidBegin in SD Card
File dir = new File(filepath.getAbsolutePath() + "/Hello/");
dir.mkdirs();
// Create a name for the saved image
File file = new File(dir, pic_name+".png");
// Notify the user on successful save
Toast.makeText(this, "Image Saved to SD Card", Toast.LENGTH_SHORT).show();
try {
// Image starts saving
output = new FileOutputStream(file);
our_img.compress(Bitmap.CompressFormat.PNG, 100, output);
output.flush();
output.close();
}
// Catch exceptions
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// to see saved images in the gallery view.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
*the program can take picture
*create a folder and image file too
BUT
the file created is of 0KB
and the folder is not visible in gallery
p.s i have given permissions in manifest to write the external storage and access the camera
I will be very very thankful to you if you can please provide me the solution please !!!
Seems like you haven't write the stream to your output file.Try this
byte[] buffer = new byte[1024];
int remainingData;
while ((remainingData = yourBitmapInputStream.read(buffer)) > 0)
{
output.write(buffer, 0, remainingData);
}
for writing streams into your bitmap file.