I've an app that displays a picture to its users. It sounds really simple, but I've been at it for days now trying to troubleshoot the exact problem. So what'll happen is that user will:
- Click an image;
- The image will be saved to the user's External Storage;
- The image's Uri will be taken;
- An ImageView will open the image with this Uri;
- No image appeared, throws
java.io.FileNotFoundException: /storage/emulated/....jpg: open failed: ENOENT (No such file or directory)
.
So I thought I didn't really pass the correct Uri and tried to troubleshoot from there. Then I accidentally rotated the screen and hey - my image is there! The the log file showed this when I rotated it a few times:
android.graphics.Bitmap@49361a20
android.graphics.Bitmap@495c42c8
android.graphics.Bitmap@496ac1e0
android.graphics.Bitmap@495b2b28
Is this displaying the memory location? Is it supposed to be different even after screen rotation?
With this information, is there anywhere else I should look into to solve this problem? I could rule out that the Uri is invalid, as it is showing the correct image after rotating the screen.
This is the code (of a utility class) involved to download the image clicked; This method seems to work well and the image is saved to the correct directory.
public void downloadFile(String url) {
File folder = new File(Environment.getExternalStorageDirectory() + directory);
String fileName = url.substring(url.lastIndexOf("/") + 1);
String filePath = folder.getPath() + "/" + fileName;
File file = new File(filePath);
fileUri = Uri.fromFile(file);
if (!folder.exists()) {
Log.i(TAG, "Worka folder is not found, creating one now");
folder.mkdir();
} else {
Log.i(TAG, "Worka folder is found");
if (file.exists()) {
Log.i(TAG, "Found a file with the same name, deleting/replacing it now");
file.delete();
}
}
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI)
//.setAllowedOverRoaming(false).setTitle("Roaming is not available")
.setDestinationInExternalPublicDir(directory, fileName);
downloadManager.enqueue(request);
Log.i(TAG, "downloadFile() is successful, " + fileName + " is saved to Worka directory");
}
public Uri getFilePath() {
return fileUri;
}
To make sure it gets passed from an activity to another activity;
FileDownload fileDownload = new FileDownload(getApplicationContext());
fileDownload.downloadFile(conversation.getMessage());
Uri fileUri = fileDownload.getFilePath();
if (fileUri != null) {
Log.i(TAG, "fileUri: " + fileUri.toString());
Intent intent = new Intent(BulletinPostActivity.this, ImageViewingActivity.class);
intent.putExtra("imageUri", fileUri.toString());
startActivity(intent);
Finally, getting Bitmap from the passed Uri:
I then tried using AsyncTask here, to make sure the bitmap gets loaded properly... but I'm unsure what to code to accomplish this.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
String imagePath = getIntent().getStringExtra("imageUri");
imageUri = Uri.parse(imagePath);
touchImageView = (TouchImageView) findViewById(R.id.image_viewing_image_view);
if (imageUri != null) {
new loadBitmap(imageUri).execute();
}
}
public class loadBitmap extends AsyncTask<Void, Integer, Bitmap> {
Uri uri;
public loadBitmap(Uri uri) {
this.uri = uri;
}
@Override
protected Bitmap doInBackground(Void... params) {
getBitmap();
return bitmap;
}
public Bitmap getBitmap() {
try {
Log.i(TAG, "Attempting to get the bitmap from imageUri");
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
Log.i(TAG, "Successfully gotten the bitmap from imageUri: " + bitmap);
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap == null) {
getBitmap();
} else {
touchImageView.setImageBitmap(bitmap);
}
}
}