I get an image from the camera or gallery and set it to my imageview. Unfortunately when the screen gets rotated the imageview shows nothing.
How can I keep the image visible ?
This is the code where I get the image :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case REQUEST_IMAGE_CAPTURE:
// if taking
if (resultCode == RESULT_OK && null != data && TAKE_OR_PICK == 1) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
int width = imageBitmap.getWidth();
int height = imageBitmap.getHeight();
if(height>width) {
int crop = (height - width) / 2;
Bitmap cropImg = Bitmap.createBitmap(imageBitmap, crop, 0, width, width);
image.setImageBitmap(cropImg);
}
else if (width>height){int crop = (width - height) / 2;
Bitmap cropImg = Bitmap.createBitmap(imageBitmap, crop, 0, height, height);
image.setImageBitmap(cropImg);}
else {image.setImageBitmap(imageBitmap);}
}
break;
case RESULT_LOAD_IMAGE:
// if choosing
if (resultCode == RESULT_OK && null != data && TAKE_OR_PICK == 2) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
int width = imageBitmap.getWidth();
int height = imageBitmap.getHeight();
if(height>width) {
int crop = (height - width) / 2;
Bitmap cropImg = Bitmap.createBitmap(imageBitmap, crop, 0, width, width);
image.setImageBitmap(cropImg);
}
else if (width>height){int crop = (width - height) / 2;
Bitmap cropImg = Bitmap.createBitmap(imageBitmap, crop, 0, height, height);
image.setImageBitmap(cropImg);
}
else {image.setImageBitmap(imageBitmap);}
}
I've tried to use onSaveInstanceState() but can't get it to work for a bitmap. Is there another way to achieve this ?
There are generally three ways to do this:
As some of the answers suggested, you could distinguish the cases of
your activity being created for the first time and being restored
from savedInstanceState. This is done by overriding
onSaveInstanceState and checking the parameter of onCreate.
2.You could lock the activity in one orientation by adding android:screenOrientation="portrait" (or "landscape") to
in your manifest.
3.You could tell the system that you meant to handle screen changes for yourself by specifying
android:configChanges="orientation" in the tag. This way
the activity will not be recreated, but will receive a callback
instead (which you can ignore as it's not useful for you)
as Gazi said if the user is not allowed to rotate the screen that "close" the option via the Manifest.
if it's not relevant you shall have a function that
fillAllData()
that is called within "onResume" and inside the function if you have the bitmap add it into the image (you can keep it with onSaveInstance)
private ImageView mMyImageView;
private String tempFileName;
onCreate(){
setContentView(R.layout.myLayout);
mMyImageView = (ImageView)findViewById(R.id.myImageView);
}
onActivityResult(){
//do all your code plus this:
tempFileName = random string;
save bitmap after process in tempFileName
update in application some flag that a temp file image is available;
}
onResume(){
if temp file name is available load bitmap into your image view.
}
What happening in your case is, if you rotate your device the activity is recreated.Try adding the below inside activity tag of your AndroidManifest.xml file. Hope this helps.
android:configChanges="orientation | screenSize"
Related
low quality when capture picture and send it image view
when imgCamera button pressed
case R.id.imgCamera:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
break;
**the activity result :**
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CAMERA_REQUEST:
mPhotoEditor.clearAllViews();
Bitmap photo = (Bitmap) data.getExtras().get("data");
mPhotoEditorView.getSource().setImageBitmap(photo);
break;
case PICK_REQUEST:
try {
mPhotoEditor.clearAllViews();
Uri uri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
mPhotoEditorView.getSource().setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
please help me I want to get the best quality for the picture captured
To save the full-size image you need to do much more stuff.
data.getData();
This would return image thumbnail which is a low-quality image for the original one.
I can't find an accurate guide than the official documentation. check this link from Android Developer documentation. Following it, you would save the high-quality image easily instead of a low-quality one. Not to mention, You would learn about FileProivder and storage (Maybe you like to save it internal storage or external storage).
Be patient .. happy coding
my comment tells you want is wrong. Here's the solution:
first, modify your camera intent:
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
_photoUri = createImageUri();
// Continue only if the File was successfully created
if (_photoUri != null) {
//setflags is required to clear flag_activity_new_task that is automatically set on
//direct calls. If not cleared, you get instant returns from the app.
takePictureIntent.setFlags(0);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, _photoUri);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
private Uri createImageUri() {
return FileProvider.getUriForFile(this
, this.getApplicationContext().getPackageName()
, new File(Environment.getExternalStorageDirectory()
, "orderphoto.jpg"));
}
this tells the camera where to put the photo.
check in your activity result for RESULT_OK to ensure they didn't cancel.
You'll need to then be able to read from the file system. Here's how our app does it: Note i can't be positive i'm not referencing a custom function in this. YMMV.
private Bitmap DecodeFile(Uri fileUri) {
/* There isn't enough memory to open up more than a couple camera photos */
/* So pre-scale the target _bitmap into which the file is decoded */
/* Get the size of the ImageView */
int targetW = _imageView.getWidth();
int targetH = _imageView.getHeight();
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileUri.getPath(), bmOptions);
// TODO: 2/25/2019 Update to BitmapFactory.decodeStream()
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
if (photoW == 0 || photoH == 0) {
AppUtility.ShowToast("BitmapFactory.Decode: File Decoding Failed!");
}
/* Figure out which way needs to be reduced less */
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
/* Set _bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
/* compress/shrink the bitmap */
// TODO: 2/25/2019 Update to BitmapFactory.decodeStream()
return BitmapFactory.decodeFile(fileUri.getPath(), bmOptions);
}
When you use this, it does all the hard work for you and sizes it to the screen. Note that some samsung devices lie about the orientation so you may have problems about that.
i was following this link Android get Orientation of a camera Bitmap? And rotate back -90 degrees to rotate my image if/when necessary, but its not working for me, i get this error
05-28 23:29:30.049 9735-9735/ss.sealstudios.com.socialstories E/JHEAD: can't open '/document/508'
but checking it like below looks like there pointing in the right place
05-28 23:29:30.049 9735-9735/ss.sealstudios.com.socialstories I/System.out: bitmap uri content://com.android.providers.downloads.documents/document/508 0
//the 0 on the end is me checking for the rotation
i was wondering if this was build version specific like getting the real path from a URI as running this code on my marshmallow device gives me an entirely different result (this result, ie: error codes, is from a kitkat device), but this has defeated me for some weeks now following all sorts of answers to no avail, can anyone weigh in and help me please, here's what I'm trying to do
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data
!= null
&& data.getData() != null)
{
Uri uri = data.getData();
try {
BitmapFactory.Options bitmapOptions = new
BitmapFactory.Options();
bitmapOptions.inSampleSize = (int) 4;
InputStream inputStream =
getContentResolver().openInputStream(uri);
Bitmap scaledBitmap = BitmapFactory.decodeStream(inputStream,
null, bitmapOptions);
ExifInterface exif = new ExifInterface(uri.getPath());
int rotation =
exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotationInDegrees = exifToDegrees(rotation);
System.out.println("bitmap uri " + uri + " " + rotation);
Matrix matrix = new Matrix();
if (rotation != 0f){
matrix.preRotate(rotationInDegrees);
Bitmap.createBitmap(scaledBitmap, 0,
0,scaledBitmap.getWidth(),scaledBitmap.getHeight(),
matrix, true);
imageView.setImageBitmap(scaledBitmap);
}else
imageView.setImageBitmap(scaledBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static int exifToDegrees(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
}
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
return 270; }
return 0;
}
many thanks
ExifInterface exif = new ExifInterface(uri.getPath());
This will not work. If you call getPath() on a Uri, you are doing it wrong, as that is meaningless for most Uri values, particularly those with a content scheme, as your has.
Since the SDK's ExifInterface only works with local files, you will need other EXIF code. I use some code from the AOSP for this. That version of ExifInterface can work with an InputStream, so you can get a fresh InputStream for the content identified by the Uri and pass that to the alternative ExifInterface.
The scope: I want to take a picture via intent and save the picture to the internal storage of my app.
Then I want to load a scaled version into a byte array (from inputstream), save this scaled image as byte array into SQLight.
After saving it to the database I want to delete the picture.
(This question only is about saving the image to internal storage, the scope is only here because there is always someone that ask about it)
The problem: I'm stuck at saving the picture to the internal storage.
I'll add examples from my debugging session as comments behind the variables to show the values i got while testing.
I have an ImageView which has an onClickListener that starts the takePictureIntent:
With following global attributes:
Uri mCurrentPhotoUri; //URI to file
File mCurrentPicture; //the current picture don't know if I need it somewhere but for complete understanding of code
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Intent for the on-board camera
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//device has camera
if(takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
//create a file with path the code below
photoFile = createImageFile(); //sets photoFile to: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
} catch (IOException e) {
e.printStackTrace();
}
//file has been created, set members and add Extra to intent, then start intent.
if(photoFile != null) {
mCurrentPicture = photoFile; // well, same as above
mCurrentPhotoUri = Uri.fromFile(photoFile); // this looks somehow wrong, but I don't know much about URIs: file:///data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); //same URI as above that extra should be needed to tell the cam that I don't want to save to the default path but my app path
startActivityForResult(takePictureIntent, 10); //start the intent and use requestcode 10 for onActivityResult ...
}
}
}
});
The creation of the file path:
//code from google developers with some changes.
private File createImageFile() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); //from today value: 20151105_092219
String imageFilename = "JPEG_" + timestamp + "_"; // concat is this: JPEG_20151105_092219_
File storageDir = this.getDir("photo", MODE_PRIVATE); //String path is: /data/data/my.app.project/app_photo
storageDir.mkdirs();
File image = File.createTempFile(imageFilename, ".jpg", storageDir); //String path is: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
mCurrentPhotoPath = "file:" + image.getAbsolutePath(); //here I put the absolute path into static mCurrentPhotoPath, concate with the "file:" from googledeveloper guide: file:/data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
return image;
}
So the camera opens and I can take a picture and I'm ask if I want to save that picture (all from the build-in camera app, device is a samsung galaxy note).
Then my onActivityResult-Method is called:
I used data as parameter because I used the mini byte array for something, but with the custom storage this returns null and it isn't used anymore.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch(requestcode) {
...
case 10:
setImageView(ivPreview1, data, 0);
ivPreview.setVisibility(View.VISIBLE);
break;
...
}
...
}
}
Method setImageView:
private void setImageView(ImageView iv, Intent data, int index) {
try {
Uri u = mCurrentPhotoUri; //sets u to: file:///data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
File file = new File(u.getPath()); //sets file to: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
Bitmap bm = null;
ByteArrayOutputStream baos = null;
int orientation = 0;
if (file.exists()) { //this is true
//found that somewhere in the developer training:
ExifInterface exif = null;
try {
exif = new ExifInterface(photoUri.getPath());
} catch (IOException e) {
e.printStackTrace();
}
if(exif != null)
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); //is 0 (i didn't rotate the tablet)
//resulution I want to resize the image to:
int reqWidth = 960, reqHeight = 1280;
//exchange values if orientation doesn't match landscape
if (orientation == 0 || orientation == 270) {
int temp = reqWidth;
reqWidth = reqHeight;
reqHeight = temp;
}
//this I used before I changed to internal storage to change the size of the image code below
bm = ImageManager.decodeSampledBitmapFromFile(u.getPath(), reqWidth, reqHeight); // returns null because of this everything following is null too.
if (orientation == 90 || orientation == 180 || orientation == 270) {
Matrix matrix = new Matrix();
// rotate the Bitmap
if (orientation == 90)
matrix.postRotate(90F);
else if (orientation == 270)
matrix.postRotate(-90F);
else
matrix.postRotate(180F);
// recreate the new Bitmap
bm = Bitmap.createBitmap(bm, 0, 0,
bm.getWidth(), bm.getHeight(), matrix, true);
}
baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 50, baos);
}
iv.setImageBitmap(bm);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Could not take Photo: ", e);
}
}
The following methods that I used to decode the file (customisation of: http://developer.android.com/downloads/samples/DisplayingBitmaps.zip ):
The line with BitmapFactory.decodeFile(filename, options); also creates a log entry: D/skia: --- SkImageDecoder::Factory returned null
public static Bitmap decodeSampledBitmapFromFile(String filename,
int reqWidth, int reqHeight) {
//this gets parameters:
// reqHeight: 960, reqWidth: 1280 and filename: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filename, options); // this adds outHeight and outWidth to -1 (variables from options)
//this also creates a log entry: D/skia: --- SkImageDecoder::Factory returned null
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(filename, options);
return bmp;
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// BEGIN_INCLUDE (calculate_sample_size)
// Raw height and width of image
final int height = options.outHeight; //is -1
final int width = options.outWidth; //is -1
int inSampleSize = 1;
//because its obviously smaller in both statements code will not be executed so it returns 1
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger inSampleSize).
long totalPixels = width * height / inSampleSize;
// Anything more than 2x the requested pixels we'll sample down further
final long totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels > totalReqPixelsCap) {
inSampleSize *= 2;
totalPixels /= 2;
}
}
return inSampleSize;
// END_INCLUDE (calculate_sample_size)
}
I'm stuck at this for several days now I don't have any ideas that could solve my problem. This is also due to lack of android knowledge and the fact that i can't use emulators on my pc so i can't even look in the app folder to see if a picture was taken.
Try to get the path for storing temporary image like below.which will return your app folder location.and add the permission as well.
File dir = context.getExternalFilesDir(null)+"/"+"photo";
Add uses-feature for camera access too.
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true" />
Official documentation.
I am using the Xamarin.Forms Camera sample from here - https://github.com/XForms/Xamarin-Forms-Labs-Samples/tree/master/XF.Labs.CameraSample I am able to select or take a photo.
private async Task SelectPicture()
{
mediaPicker = DependencyService.Get<IMediaPicker>();
imageSource = null;
var mediaFile = await mediaPicker.SelectPhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
imageSource = ImageSource.FromStream(() => mediaFile.Source);
img.Source = imageSource;
}
private async Task TakePicture()
{
mediaPicker = DependencyService.Get<IMediaPicker>();
imageSource = null;
var mediaFile = await mediaPicker.TakePhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
imageSource = ImageSource.FromStream(() => mediaFile.Source);
img.Source = imageSource;
}
the code for the image is simply
img = new Image
{
BackgroundColor = Color.White,
Aspect = Aspect.AspectFit
};
There are a couple of issues:
First one. You can take a photo or select a stored one and it will then show it on the page. If you select a photo it displays it correctly, either portrait or landscape. When you take a photo, it only displays in landscape mode, so if the image was taken in portrait, the image shows on the side. This isn't catastrophic, but it would be better to show the image how it was taken.
The second issue is a bit more drastic, if you press the device's back button when you are either in the camera or the image gallery then the screen goes blank and then you get a message stating the app has stopped responding.
I have only tried this on Android so far. Does anyone have any ideas on how I can solve the above problems?
EDIT: I have managed to fix the crashing on back button, but the image still displays on its side for Android, but displays correctly for iOS
I would venture to guess there are a couple of issues here. One the Xamarin.Forms.Labs dependency injection handler on Android is 1) not checking for needed rotation, 2) is not checking for either external storage or is not handling onActivityCancelled.
The easy solution to your problem would be to use the Xamarin.Mobile Xamarin.Mobile I cannot 100% confirm it will handle everything but if it does this would be a quick and easy solution.
The more difficult option that will give you more control would be to roll your own platform specific implementation. I am not going to go into how DI works either you know or can see the Accessing Native Features
Here is an example of Android take picture with code for figuring out if the storage is external and whether or not rotation is needed.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
//FinishActivity(requestCode);
try
{
if (resultCode == Result.Ok)
{
switch (requestCode)
{
case TAKE_PHOTO:
{
Java.IO.File photo = null;
if (isMounted)
{
photo = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.ToString(), SharedLibrary.strPhotoLocation);
}
else
{
photo = new Java.IO.File(CacheDir, SharedLibrary.strPhotoLocation);
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
options.InSampleSize = 4;
options.InPurgeable = true;
options.InInputShareable = true;
try
{
//Cleanup code... removed this in favor of using options.InJustDecodeBounds to get info about the bitmap
//instead of creating it twice in memory
//Bitmap imageBitmap = BitmapFactory.DecodeFile(photo.AbsolutePath, options);
//int w = imageBitmap.Width;
//int h = imageBitmap.Height;
BitmapFactory.DecodeFile(photo.AbsolutePath, options);
int w = options.OutWidth;
int h = options.OutHeight;
Matrix matrix = new Matrix();
matrix.SetRotate(getNeededRotation(photo.AbsolutePath));
options.InJustDecodeBounds = false;
//Bitmap imageBitmap = Bitmap.CreateBitmap(BitmapFactory.DecodeFile(photo.AbsolutePath, options), 0, 0, w, h, matrix, false);
Bitmap imageBitmap = Bitmap.CreateScaledBitmap(BitmapFactory.DecodeFile(photo.AbsolutePath, options), w, h, false);
//...
Get Mounted
private System.Boolean isMounted
{
get
{
return (System.Boolean)Android.OS.Environment.ExternalStorageState.Equals(Android.OS.Environment.MediaMounted);
}
}
GetRotationNeeded
private int getNeededRotation(string filepath)
{
ExifInterface exif = new ExifInterface(filepath);
int orientation = exif.GetAttributeInt(ExifInterface.TagOrientation, -1);
int rotate = 0;
switch (orientation)
{
case 6:
{
rotate = 90;
break;
}
case 3:
{
rotate = 180;
break;
}
case 8:
{
rotate = 270;
break;
}
default:
{
rotate = 0;
break;
}
}
exif.Dispose();
return rotate;
}
you can check orientation by using 'mediaFile.Exif.Orientation' to check whether it's portrait or Landscape.(' TopLeft'--> Portrait.) And then set photo orientation before saving using,
mediaFile.Exif.Orientation = ExifLib.ExifOrientation.TopLeft;
I have looked all over for a solution to my problem and just can't seem to figure it out. I'm sure it is probably 1 or 2 simple lines and hopefully someone can steer me in the right direction.
In my app, a user can click a button that will open the gallery. Once they select an image, it will display that image in an ImageView within my app. That part is working perfectly fine. Originally, I just had it return a uri from the gallery and I would directly display that with this:
imageView1.setImageURI(myUri);
Well, obviously I am now running into the dreaded "Out Of Memory" error if the user reloads that page several times in a row so I'm having to clean up my code to scale down the image. I have done this by implementing a bitmap class that turns the image into a bitmap and scales it down for me. Now, my ImageView display code looks like this:
imageView1.setImageBitmap(bitmap1);
That part is working fine as well. HERE IS THE PROBLEM:
I convert the uri path to a string and then save that in a SharedPreference. This is so that when the user exits the application and the comes back later, the image that they set automatically displays. I convert the uri like this:
...
selectedImageUri = data.getData();
String selectedImagePath;
selectedImagePath = getPath(selectedImageUri);
...
The old method to retrieve the SharedPreference String, convert it to uri, then display it was working fine. (except for the Out Of Memory error of course) It looked like this:
Uri myUri = Uri.parse(selectedImagePath);
imageView1 = setImageURI(myUri);
"selectedImagePath" is obviously the String that I retrieved from the SharedPreference. Again, this worked fine but would throw the error if reloaded too many times.
The part that IS NOT WORKING now is when I try to implement the new Bitmap conversion so that I can scale the bitmap and not get the memory error. Here is the code for that:
Uri myUri = Uri.parse(selectedImagePath)
Bitmap bitmap = getThumbnail(myUri);
imageView1.setImageBitmap(bitmap);
This displays nothing. The original image choosing displays the image fine but when I return to this screen and it tries to parse the string from the SharedPreference and then convert it to the bitmap, nothing ever displays. The code for the "getThumbnail" method was taken directly from THIS POST --->
How to get Bitmap from an Uri?
It is the 3rd answer down.
Anyone have any ideas? Sorry for the super long post but I'd rather over explain my problem than not give enough info. Sorry if this was answered somewhere else. I've been hunting through other questions for hours and have just not found anything that solves my problem.
Thanks.
I figured it out so here is what I did for anyone else having this unique problem. After the image is chosen from the gallery and it returns the intent, I got the data from that intent via this code:
selectedImageUri = data.getData();
Then I got the path from that via this:
selectedImagePath = getPath(selectedImageUri);
Which made a call to this "getPath" method:
public String getPath(Uri uri)
{
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
Then I saved "selectedImagePath" as a SharedPreference string.
Later, to retrieve that string and convert it back to showing an image, I first retrieved the SharedPreference string and converted it back to "selectedImagePath". Then, I set it in the ImageView like this:
targetImage = (ImageView)findViewById(R.id.imageView1);
targgetImage.setImageBitmap(decodeSampledBitmapFromResource(selectedImagePath, 200, 200));
which made a call to the following methods:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 2;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(String resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(resId, options);
}
It's a heck of a lot of code to do a fairly simple task but it works so I'm happy and moving on. Hopefully this will help someone else who needs to accomplish the same thing.