I have android code which creates an image and saves them. For most of the user everything works fine, but for a few, they are unable to view the picture, what could be the possible reason?
Here is my code snippet for creating image
public static String takeScreenshot(View view, boolean temp) {
String name;
if (temp) {
name = "last_shared";
} else {
Date now = new Date();
name = (String) android.text.format.DateFormat.format("yyyyMMdd_hhmmss", now);
}
// create directory if it does not exist
File folder = new File(Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) +
"/Quoted");
if (!folder.exists()) {
// NOTE: Should this be mkdirs()?
folder.mkdir();
}
try {
// image naming and path to include sd card appending name you choose for file
// String mPath = Environment.getExternalStorageDirectory().toString() + "/Quoted/quote_" + name + ".jpg";
String mPath = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
.toString() + "/Quoted/quote_" + name + ".jpg";
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
return mPath;
//openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
return "";
}
public static void refreshGallery(String filename, Context context) {
MediaScannerConnection.scanFile(context,
new String[]{filename}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d("ExternalStorage", "Scanned " + path + ":");
Log.d("ExternalStorage", "-> uri=" + uri);
}
}
);
}
The issue is happening on device like Xiaomi Redmi 3S Android 6.0 and Asus ZenFone 2 Android 6.0.
I have tested app on other 6.0 devices and it works just well.
As far as I can think, the cause could be:
1. Environment.DIRECTORY_PICTURES is not resolving for these phones. So should I use mkdirs() instead?
2. Whatever I am doing is it the right way to do it?
If anyone has faced similar issues please help me. I would love any kind of hints. Thanks.
Related
As in my Drawing art project I want Save Painted images to storage or retrieval same image in my app Recycler view with Android Java & I got & save images from below android 11 but not from above 11 what should I do ??
Thankful if got help from someone & if I got solution than sure put in my answer....Thank-You
Hi First add below line to manifest in application tab
for make directory in android 10 & solve error in android 8
<application
android:requestLegacyExternalStorage="true"
android:hardwareAccelerated="false"
android:largeHeap="true" />
& than try below code / method
in blank space set folder name of your wish and put this in res - values - string
<resources>
<string name="app_folder_name">Your_Folder_name</string>
</resources>
Then add this method to your Activity.
private void saveToGallery() {
String parentPath="";
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// for above android 11
parentPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + Environment.DIRECTORY_PICTURES + File.separator + getString(R.string.app_folder_name);
}else{
// for below android 11
parentPath = Environment.getExternalStorageDirectory() + File.separator + getString(R.string.app_folder_name);
}
File parentFile = new File(parentPath);
Log.e("TAG", "saveToGallery1: "+parentFile);
if (!parentFile.exists()){
parentFile.mkdirs();
}
File imageFile = new File(parentFile, "drawing"+System.currentTimeMillis() + ".png"); // Imagename.png
FileOutputStream out = null;
try {
out = new FileOutputStream(imageFile);
Bitmap bmp = binding.paintView.save();
Common.DRAWING_BITMAP = bmp;
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image
out.flush();
out.close();
// Tell the media scanner about the new file so that it is // immediately available to the user.
MediaScannerConnection.scanFile(PaintDrawActivity.this, new String[]{imageFile.getAbsolutePath()}, null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.e("ExternalStorage1", "Scanned " + path + ":");
Log.e("ExternalStorage1", "-> uri=" + uri);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void getMyWorkImagesFromStorage() {
File file;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// for above android 11
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), Environment.DIRECTORY_PICTURES + File.separator + getString(R.string.app_folder_name));
} else {
// for below android 11
file = new File(Environment.getExternalStorageDirectory() + File.separator + getString(R.string.app_folder_name));
}
File[] files = file.listFiles();
if (files != null) {
for (File file1 : files) {
if (file1.getPath().endsWith(".png") || file1.getPath().endsWith(".jpg")) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(file1.getAbsolutePath(), bmOptions);
myWorkItems.add(new MyGalleryItem(bitmap, file1.getName()));
Common.MY_GALLERY_IMAGES = myWorkItems;
}
}
if (files.length == 0) {
binding.tvEmpty.setVisibility(View.VISIBLE);
} else {
binding.tvEmpty.setVisibility(View.GONE);
}
}
}
According to this link(How to programmatically take a screenshot in Android?), I used the answer to take a capture and save it on my device's external memory.
I have all the permission cleared, and according to the log, the file is not empty at all. But I can't find the file neither on the gallery nor the file explorer.
Why is this happening? Can someone help me out with this?
On regards to Rotwang, I've figured out what the problem was.
The path of the getExternalStorageDirectory() did not seen to return a valid directory for the file to be saved.
In my case, it was about saving screenshots for the user to look on the gallery.
So, I used Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES); instead.
So, the full code for saving a screen capture is below.
private void takeScreenshot() {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, now + ".jpg");
path.mkdirs();
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
//File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(file);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.e("ExternalStorage", "Scanned " + path + ":");
Log.e("ExternalStorage", "-> uri=" + uri);
}
});
} catch (Throwable e) {
Log.e("Error", "Exception on TakeScreenshot", e);
}
}
Thanks again Rotwang.
I have created a simple application to take some user data and write it to a text file which gets saved on the external storage of my device. However, I am unable to access those files using my computer until after I have rebooted my device. Can anyone tell me why this is and if there is something I can do to fix it?
Here is the code I use to write data.
private void commitToFile(String worldOrApp, String xPos, String yPos, String orient) {
Intent intent = getIntent();
String filename = intent.getStringExtra(MainActivity.FILENAME) + ".txt";
final String position = worldOrApp + " - x: " + xPos + "; y: " + yPos + "; alpha: " + orient + "\r\n";
File myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myFolder = new File(myPath.getAbsolutePath()+"/test_folder");
if (!myFolder.exists()) {
myFolder.mkdirs();
}
File myFile = new File(myFolder, filename);
try {
FileOutputStream fileOutputStream = new FileOutputStream(myFile, true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
outputStreamWriter.write(position);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks to #CommonsWare for the direction. I found the following code at Android saving file to external storage
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
which I placed directly underneath the exception catch in my code, and updated file to myFile, which is the relevant File for my commitToFile method.
I have a method in a second class (Class2) where I pass in the values of context and uri from Class1. The second class (Class2) is a class where filters will be applied to images taken using the camera from Class1. The method in Class2 looks something like this
public void prepareImage(Context context, Uri uri) {
// BitmapFactory options
Options options = new Options();
options.inSampleSize = 2;
String path = uri.toString();
File file = new File(path);
FileInputStream fis = null; //initialize
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap img = BitmapFactory.decodeStream(fis);
Log.i(TAG, "Bitmap img: " + img);
//more code below, but above this comment is where the issue is
}
I am noticing that FileInputStream is returning null, therefore BitmapFactory.decodeStream is decoding nothing. There are two things that I think are issues but am not sure how to address them. First, I was wondering if I am receiving null for FileInputStream because I am using a path that is formed from uri.toString(). Or does that matter? The string path value is correct.
The second issue is that if my phone is tethered to the computer, after taking an image using my application, the image file does not seem to register until after I unplug the device from my computer. Only after I unplug my device from the computer does all my images come up in the gallery folder. So my suspicion is that file is not being found! There is evidence of this from logcat.
Anyway, I do not know how to get around this conflict. Maybe I need to save images in a different way. Here is how I am saving images in Class1.
File imgFileDir = getDir();
if (!imgFileDir.exists() && !imgFileDir.mkdirs()) {
Log.e(TAG, "Directory does not exist");
}
//Locale.US to get local formatting
SimpleDateFormat timeFormat = new SimpleDateFormat("hhmmss", Locale.US);
SimpleDateFormat dateFormat = new SimpleDateFormat("ddMMyyyy", Locale.US);
String time = timeFormat.format(new Date());
String date = dateFormat.format(new Date());
String photoFile = date + "_nameofapp_" + time + ".jpg";
String filename = imgFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(arg0);
fos.flush();
fos.close();
} catch (Exception e) {
Log.e(TAG, "Image could not be saved");
e.printStackTrace();
}
I also use a helper method
private File getDir() {
File sdDir = Environment.
getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "NameOfApp");
}
Lastly, I tried running the application untethered to my computer to see if it would work and it does not. The behavior is just the same, images that I take picture of does not show up in the gallery until I replug the device to my computer, and then all the images I took show up in the gallery. Why?
Per request, I am passing the URI from Class1 doing the following.
Class2 classTwo = new Class2();
classTwo.prepareImage(this, uri);
Just moving this to an answer so everyone can see:
It looks like an extra / got into your file Uri.
file:/storage/emulated/0 ...
versus
/file:/storage/emulated/0 ... (from the exception message)
:)
I'm trying to share a downloaded bitmap via Android's ShareActionProvider, and I'm having an issue actually passing the bitmap to appropriate apps (such as Messenger, Google+, Gmail). When I pass the intent with the uri, nothing happens (image isn't populated in the 3rd party app).
Here is my Intent:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
writeToDirectory(bitmap, "cached-image.png"); // write bitmap to file system in order to share
intent.putExtra(Intent.EXTRA_STREAM, getFileUri("cached-image.png"))
mShareActionProvider.setShareIntent(intent);
I'm currently saving the bitmap to file using the following:
public String writeToDirectory(Bitmap bitmap, String filename) {
assert context != null;
assert bitmap != null;
assert filename != null;
// Ensure directory exists and create if not
String path = Environment.getExternalStorageDirectory() + File.separator + "myApp";
File f = new File(path);
boolean dirExists = f.isDirectory();
if (!f.isDirectory() && !f.exists()) {
dirExists = f.mkdirs();
}
if (dirExists) {
File file = new File(sharedPrivateExternalPath, filename);
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (IOException ex) {
e(TAG, "Write failed!");
e(TAG, ex.getMessage());
ex.printStackTrace();
}
return file.toString();
} else {
return "";
}
}
and I'm retrieving the Uri with this method
public Uri getFileUri(String filename) {
assert context != null;
assert filename != null;
String path = Environment.getExternalStorageDirectory() + File.separator + "myApp";
File file = new File(path, filename);
return Uri.fromFile(file);
}
I've checked that the file gets written to the appropriate place (Uri is file:///storage/emulated/0/myApp/cached-image.png) and was able to view the image there (did an adb pull from the device), though the image doesn't get passed. I don't see any errors in the log (no FileNotFoundException or anything of the sort). Is this a file permission issue? Am I not able to share to a "non-public" location?
If I change getExternalStorageDirectory() + File.separator + "myApp"; to plain getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) it works fine... but it's bothering me it doesn't work the other way :).
Any help would be great!
Turns out it had to do with code I didn't post (surprise, surprise). I was attempting to set the shareIntent in the setOnShareTargetSelectedListener... which apparently you can't do.
My problem was with this code snippet
mShareActionProvider = (ShareActionProvider)
MenuItemCompat.getActionProvider(shareItem);
mShareActionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() {
#Override
public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
String urlKey = mImageUrlList.get(mImageGallery.getCurrentItem()) + "\n";
// This is the problem line
mShareActionProvider.setShareIntent(getImageIntent(app.getImageCache().get(urlKey)));
return false;
}
})