Fragment flips and losses Image - android

I've completely re-wrote the question to single down the scope.
I have Two Fragments that Flip around like a card(Left, Right). When the front fragment disappears flips it shows the back. Once the button is clicked again it flips to the front again but the ImageView on the front fragment is gone.
I have tried different methods of saving the data of the Image picked.
Saving the Fragment onSaveInstanceState
This gives me a Null Pointer, so I figured I needed something more constant once being created.
So now I save the image to SDCard once Picked
This I figured would work and just check the path and grab it if its flipped to the front or the activity is recreated.
Here is some Code
onCreate():
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_postcard_activity);
//UI call
frontImageView = (ImageView) findViewById(R.id.imageView);
Log.d(tag, "onCreate() Instance:" + savedInstanceState);
//fragment start
if (savedInstanceState == null) {
Log.d(tag,"Instance Null");
getFragmentManager()
.beginTransaction()
.add(R.id.postcardFrame, new CardFrontFragment())
.commit();
if(!mShowingBack){
Log.d(tag,"Not showing back");
if(newPath != null && newPath != ""){
Log.d(tag, "entered new path, not empty");
Drawable drawable = Drawable.createFromPath(newPath);
Log.d(tag, "Should be setting saved image.");
frontImageView.setImageDrawable(drawable);
}
}
}
else
{
mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
Log.d(tag, "Instance is not Null");
}
Flip Button Click Listener
//flip card
final Button cardBackButton = (Button) findViewById(R.id.cardBackButton);
cardBackButton.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
flipCard();
});
flipCard Method:
private void flipCard()
{
Log.d(tag2, "Log after flipCard:" + mShowingBack);
if(mShowingBack)
{
//Flip to front
flipFront();
return;
}
// Flip to back
flipBack();
}
I set the Image onActivityResult from their PhotoGallery
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK) {
Uri photoUri = intent.getData();
if (photoUri != null) {
try {
ImageView setImage = (ImageView)findViewById(R.id.imageView);
frontImage = MediaStore.Images.Media.getBitmap(this
.getContentResolver(), photoUri);
imageSet = true;
//save image to SD
if(imageSet == true){
Log.d(tag, "Inside Image Set if Statement");
String path = getExternalCacheDir() + "Postcards.png";
if(path != null && path != ""){
Log.d(tag, "Path is:" + path);
File file = new File(path);
newPath = file.getAbsolutePath();
Log.d(tag, "New Path:" + newPath);
if(file.exists()){
Log.d(tag, "File Exists");
Drawable d = Drawable.createFromPath(newPath);
setImage.setImageDrawable(d);
}else{
try{
Log.d(tag,"File didnt exist");
FileOutputStream out = new FileOutputStream(file);
frontImage.compress(Bitmap.CompressFormat.PNG, 90, out);
if(file.exists()){
Log.d(tag, "file exists now");
newPath = file.getAbsolutePath();
Drawable b = Drawable.createFromPath(newPath);
setImage.setImageDrawable(b);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
This is how I am accessing the image and trying to set it to my ImageView on Restart()
if(imageSet == true){
if(newPath != null && newPath != ""){
ImageView view = (ImageView) findViewById(R.id.imageView);
Drawable drawable = Drawable.createFromPath(newPath);
view.setImageDrawable(drawable);
}
}
This seems like the best route in getting the image and setting it but it wont work.
What would be best practice and how can I get it to perform the way I need it to?
Much appreciated with any help!

savedInstanceState serves a different purpose.
onSaveInstanceState (Bundle):
This method is called before an activity may be killed so that when it
comes back some time in the future it can restore its state
And, in your particular case, it may not even be required. On button click, you are changing fragments, not restarting your app.
From what I can see, you are letting the user create a postcard: a picture on one side (say, Side A) and a message on flip-side (say, Side B). When the app starts, Side A is in view. In some manner, you let the user select an image from the gallery. I will assume that onActivityResult(int, int, Intent) works as expected, and sets the image to ImageView - R.id.imageView. When a button is clicked, the view is changed to Side B. And when the button is clicked again, the view changes to Side A, but the image selected by user is not there.
One thing you can do inside onActivityResult(int, int, Intent) is: save the path of the image in SharedPreferences.
SharedPreferences preferences;
final String PREFS = "your.application.name.prefs";
// Keyword to find the path
final String IMAGE_SELECTED_BY_USER = "image_selected_by_user";
// Use a default image when the user starts the app for the first time
// or if the retrieved path points to a deleted image etc.
final String PATH_TO_A_DEFAULT_IMAGE = "path_to_a_default_image"
#Override
protected void onCreate(Bundle savedInstanceState) {
....
....
preferences = getActivity().getSharedPreferences(PREFS, 0);
imagePath = preferences.getString(IMAGE_SELECTED_BY_USER, PATH_TO_A_DEFAULT_IMAGE);
frontImageView = (ImageView) findViewById(R.id.imageView);
Drawable drawable = null;
if (new File(imagePath).exists()) {
drawable = Drawable.createFromPath(imagePath);
} else {
drawable = Drawable.createFromPath(PATH_TO_A_DEFAULT_IMAGE);
}
frontImageView.setImageDrawable(drawable);
getFragmentManager()
.beginTransaction()
.add(R.id.postcardFrame, new CardFrontFragment())
.commit();
....
....
}
In onActivityResult(int, int, Intent), save the image path:
if(file.exists()){
Log.d(tag, "File Exists");
Drawable d = Drawable.createFromPath(newPath);
setImage.setImageDrawable(d);
Editor editor = preferences.edit();
editor.putString(IMAGE_SELECTED_BY_USER, newPath);
editor.commit();
} else{
try{
Log.d(tag,"File didnt exist");
FileOutputStream out = new FileOutputStream(file);
frontImage.compress(Bitmap.CompressFormat.PNG, 90, out);
if (file.exists()) {
Log.d(tag, "file exists now");
newPath = file.getAbsolutePath();
Drawable b = Drawable.createFromPath(newPath);
setImage.setImageDrawable(b);
Editor editor = preferences.edit();
editor.putString(IMAGE_SELECTED_BY_USER, newPath);
editor.commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
This way, when the user starts the app, he/she will see either the default image, or an image previously selected.
Where savedInstanceState would be useful: Let's say you give the user an option of writing a short message on Side B. Now, if while writing the message, the user rotates the device from Landscape to Portrait (or vice-versa), the message he/she wrote will be gone because the activity will be destroyed and recreated. To save the message, you would use onSaveInstanceState(Bundle):
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("Text_To_Save", someEditText.getText().toString());
}
On rotation, activity's onCreate(Bundle)' will be called. The bundle passed is the same one fromonSaveInstanceState(Bundle)`. To retrieve the text:
String savedString = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
if (savedInstanceState.contains("Text_To_Save")) {
savedString = savedInstanceState.getString("Text_To_Save");
}
}
someEditText.setText(savedString);
}

Related

How can I send an image from an imageview, after taking a picture, to pc via bluetooth?

I take photo
Photo gets stored in ImageView
I want to be able to send that photo stored in the ImageView to my pc via Bluetooth when user selects Send To Pharmacy button.
Is this possible? Since the image is constantly changing, how would I do this? I have looked up some tutorials and StackOverflow questions but they all seem to be focused on images in a drawable folder already.
But in this case, the image is different every time the user takes a photo. I just want to know how I can send the current photo that is in the ImageView, and send it to a PC via Bluetooth. Thanks for any help I appreciate this.
package com.cognizant.expressprescriptionregistration;
import static android.os.Environment.getExternalStoragePublicDirectory;
public class Register extends AppCompatActivity {
Button bPicButton;
ImageView imageView;
String pathToFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
bPicButton = findViewById(R.id.bTakePhoto);
imageView = findViewById(R.id.imagePrescription);
// Ask for permission for Camera and Storage
if (Build.VERSION.SDK_INT >= 23){
requestPermissions(new String[] {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// if camera successfully pops up and takes photo, set photo in ImageView
if (resultCode == RESULT_OK){
if (requestCode == 1){
Bitmap bitmap = BitmapFactory.decodeFile(pathToFile);
imageView.setImageBitmap(bitmap);
}
}
}
// Take Picture button onClick listener
public void takePhoto(View view) {
setPhotoTaken();
}
private void setPhotoTaken() {
Intent takePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Make sure the app can handle our intent
if (takePhoto.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
// Created Photo file
photoFile = createPhotoFile();
// Get path of our photo file
if (photoFile != null) {
pathToFile = photoFile.getAbsolutePath();
Uri photoUri = FileProvider.getUriForFile(Register.this, "com.cognizant.expressprescriptionregistration.fileprovider", photoFile);
takePhoto.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(takePhoto, 1);
}
}
}
// Create the file where the photo will be stored
private File createPhotoFile() {
// Name of file
String name = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// Location of storage
File storedDir = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File photo = null;
try {
// Creates file in storedDir
photo = File.createTempFile(name, ".jpg", storedDir);
} catch (IOException e) {
e.printStackTrace();
}
return photo;
}
// Send to Pharmacy Button
public void sendToPharmacy(View view) {
}
}
You can get current image from ImageView by getting the bitmap from ImageView:
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
After this you can save and share the bitmap.

Update Android Image Bitmap to SQLite Blob

I am trying to figure out where I went wrong either coding or logical flaw, I created a Recipe App that takes a couple of strings and an image, all data get saved into database and on the main screen I get a list of recipes from database.
Main Screen
Add / Edit Screen
Creating or Adding new Data is working as expected, all data get saved. The problem is everything can be updated except for the Image once it has been saved any second attempt doesn't seem to affect the image, the image remains the same.
The core principle is to set data to the views (When user start the activity onCreate or resume the activity onResume) and get data from the views (When user leaves onPause and onSaveInstanceState just incase an update was made)
Code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_edit);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
enableEdit();
fab.hide();
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recipeDAOImp = new RecipeDAOImp(this);
recipeDAOImp.open();
findViews();
rowId = (savedInstanceState == null) ? null :
(Long) savedInstanceState.getSerializable(RecipeDAOImp.KEY_ID);
if (rowId == null) {
Bundle extras = getIntent().getExtras();
rowId = extras != null ? extras.getLong(RecipeDAOImp.KEY_ID)
: null;
}
populateData();
disableEdit();
}
private void findViews() {
// Finds Views and Set onClick to imageButton
}
private void disableEdit() {
// Disable Views
}
private void enableEdit() {
// Enables Views
}
private void populateData() {
// If rowId is available then user is trying to Edit Recipe
if (rowId != null) {
setTitle("Edit Recipe");
Recipe recipe = new Recipe(rowId);
Cursor cursor = recipeDAOImp.getRecipe(recipe);
startManagingCursor(cursor);
title.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_TITLE)));
ingredients.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_INGREDIENTS)));
steps.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_STEPS)));
category.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_CATEGORY)));
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), DbBitmapUtility.getImage(cursor.getBlob(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_IMAGE))));
image.setBackground(bitmapDrawable);
// Else user is Adding a new Recipe
} else {
fab.hide();
setTitle("Add Recipe");
enableEdit();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
outState.putSerializable(RecipeDAOImp.KEY_ID, rowId);
}
#Override
protected void onPause() {
super.onPause();
saveState();
}
#Override
protected void onResume() {
super.onResume();
populateData();
}
private void saveState() {
// Get the values from the views
String titleString = title.getText().toString();
String ingredientString = ingredients.getText().toString();
String stepsString = steps.getText().toString();
String categoryString = category.getText().toString();
// Get the image from imageButton
Drawable drawable = image.getBackground();
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
byte[] imageData = DbBitmapUtility.getBytes(bitmap);
// Just to clarify image is never null as the backround is a camre image
if (titleString.equals(null) || "".equals(titleString) || ingredientString.equals(null) || "".equals(ingredientString) || stepsString.equals(null) || "".equals(stepsString) || categoryString.equals(null) || "".equals(categoryString) || imageData.equals(null) || "".equals(imageData)) {
Toast.makeText(this, "No Data Saved", Toast.LENGTH_SHORT).show();
} else {
Recipe recipe = new Recipe(titleString, ingredientString, stepsString, categoryString, imageData);
// If rowId is not Available then user is Creating a new Recipe
if (rowId == null) {
long id = recipeDAOImp.createRecipe(recipe);
if (id > 0) {
rowId = id;
}
} else {
recipe.setId(rowId);
recipeDAOImp.updateRecipe(recipe);
}
}
}
#Override
public void onClick(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
// Set the imageButton
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), imageBitmap);
image.setBackground(bitmapDrawable);
}
}
}
DAO
#Override
public boolean updateRecipe(Recipe recipe) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_TITLE, recipe.getTitle());
contentValues.put(KEY_INGREDIENTS, recipe.getIngredients());
contentValues.put(KEY_STEPS, recipe.getSteps());
contentValues.put(KEY_CATEGORY, recipe.getCategory());
contentValues.put(KEY_IMAGE, recipe.getImage());
return sqLiteDatabase.update(DATABASE_TABLE, contentValues, KEY_ID + "=" + recipe.getId(), null) > 0;
}
What could be the problem that I can update string data but I can't really update the image once its saved?
After much research and testing, the problem was simply the image button can not be reset.
image.setBackground(bitmapDrawable);
This method above seems not to work for an update, my quick fix was simply to leave the code as it is and simply add a detection onActivityResult to determine if its actually an update then, add the byte data to database directly, rather than updating the image button and then recreate() the Activity, expensive procedure but not costly for a simple app.
if (rowId != null) {
...
recipe.setImage(DbBitmapUtility.getBytes(imageBitmap));
recipeDAOImp.updateRecipe(recipe);
recreate();
}
All Working as expected.
My guess is that the problem is in your DAO code. I have a similar setup (sqlite table with text and blob columns, both get updated), so I know that what you're trying to do is possible.

Refreshing EditText Fields on click of Camera button

I have two text fields and a button to capture image,on click of camera button it will capture image but entered text in text fields will be refreshed,
i have a method which will clear text and images(from the SD card).I have called this method in onCreate method.I dont want to clear those text fields upto capturing image,how to handle this?
Here is my code to capture image:
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(captureIntent, CAMERA_CAPTURE);
} catch (ActivityNotFoundException anfe) {
String errorMessage = "Device doesn't support capturing images!";
}
}
});
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
// user is returning from capturing an image using the camera
if (requestCode == CAMERA_CAPTURE) {
Bundle extras = data.getExtras();
Bitmap thePic = extras.getParcelable("data");
DateFormat dateFormat = new SimpleDateFormat("HH-mm-ss");
Date date = new Date();
String imgcurTime = dateFormat.format(date);
File imageDirectory = new File(ImagePath);
if (!imageDirectory.exists()) {
imageDirectory.mkdirs();
}
String _path = ImagePath + imgcurTime + ".jpg";
try {
FileOutputStream out = new FileOutputStream(_path);
thePic.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
out.flush();
} catch (FileNotFoundException e) {
e.getMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
In low memory situations the android will kill the background activities. In your situation when camera activity started the background activity which starting the camera is may be destroying. And when you came back from camera it is recreated. So persist your edit text data same them in onSavedInstance() method and reassign them in the onRetoreInstance() method.
I hope this may works.

Android - opening camera a second time

This is the first time I post something here, so I apologize in advance for any mistake what-so-ever.
This is the situation:
I'm currently developing my first android app, sort of like a tracker:
1. log in
2. select weather, temperature etc
3. press the start button that activates a background GPS service and shows you a list of other attendees
4. click on an attendee and it shows you a timeline where you can add pictures etc.
Here is where the fun starts. When I open the camera it works most of the time, but once in a while the activity that opens the camera gets destroyed and when reopening (to further progress) it opens a second camera.
When I take a picture like that it completely ignores the first picture, restarts the gps-service, messes up my timeline and shows the login dialog when I go back to the the main activity (which is programmed to only show up when starting the app).
I have read an similar topic and it might be the solution, but I can't get it to work.
The code for the camera activity:
public class AddPhotoActivity extends Activity {
private SharedPreferences savedValues;
private String mCurrentPhotoPath;
private String imageName;
private int id;
private String startRideDateTime;
private SimpleDateFormat dateInSQL = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private Date date;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_photo);
savedValues = this.getSharedPreferences("SavedValues",
Context.MODE_PRIVATE);
id = savedValues.getInt("RideId", 0);
startRideDateTime = savedValues.getString("StartRideDateTime", "");
try {
date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(startRideDateTime);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat dateInDir
= new SimpleDateFormat("yyyyMMdd_HHmmss");
startRideDateTime = dateInDir.format(date);
if (savedInstanceState == null) {
dispatchTakePictureIntent();
}
}
#Override
protected void onResume() {
super.onResume();
savedValues = this.getSharedPreferences("SavedValues",
Context.MODE_PRIVATE);
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
ex.printStackTrace();
}
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, 1);
}
}
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp;
File sdCard = Environment.getExternalStorageDirectory();
File storageDir = new File(sdCard.getAbsolutePath() + „/app/„ + id + "/" + startRideDateTime + "/photos");
storageDir.mkdirs();
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
imageName = image.getName();
return image;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (mCurrentPhotoPath != null) {
addPhotoToDb();
mCurrentPhotoPath = null;
}
} else if (resultCode == RESULT_CANCELED) {
finish();
}
}
private void addPhotoToDb() {
TimeLineDataSource timeLineDataSource = new TimeLineDataSource(this);
timeLineDataSource.open();
date = new Date();
String dateString = dateInSQL.format(date);
timeLineDataSource.createTimeLineItem(3, imageName, dateString);
timeLineDataSource.close();
finish();
}
public void onBackPressed() {
finish();
}
}
If anybody knows a solution to this I would be eternally grateful!
Update:
although I had better code after the previous suggestion it still didn't solve the problem. It seems that devices with less memory can get terminated at DVM-level, causing them to quit without onDestroy(). My issue is more or less resolved, but includes a lot of patchwork that I feel can be done in other, more efficient ways.
The code below is what I usually use for taking a photo/picking a photo. I normally include the ability to pick a previous photo or take a new photo, and I don't run into this issue.
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);
//zero can be replced with any action code to pick photo from gallery
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);
//one can be replced with any action code
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode) {
case 0:
if(resultCode == RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
imageview.setImageURI(selectedImage);
}
break;
case 1:
if(resultCode == RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
imageview.setImageURI(selectedImage);
}
break;
}
}
Also, I agree with the solution from the other post, this in particular:
In the case of a destroyed activity, when the activity result needs to
be processed, Android will recreate the Activity, passing a
savedInstanceState to onCreate. So, the remedy is to check the value
of savedInstanceState in your GetImageActivity.onCreate. If it is not
null then don't make any calls to startActivity because your Activity
is being recreated to call onActivityResult.
Optionally, if you need to preserve any state then override
onSaveInstanceState(Bundle outState) and put data you need into
outState.

ImageView not refreshing/reflecting changes

I'm using a photo picker intent to choose an image and write it to an application-private file. Most of my important source code is shown below. Once I press a button and perform the first image selection intent, then it successfully updates the image view. However, once I press the image selection button again (in the same activity), then the image view does NOT update, unless I exit and restart the activity. So I know the image is getting successfully saved, but why would the ImageView in the layout not refresh or update?
public void onResume() {
super.onResume();
ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
if (hasImage) {
myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PHOTO_PICKED:
if (resultCode == RESULT_OK) {
if (data != null) {
Bundle extras = data.getExtras();
if (extras != null) {
hasImage = true;
bmp = (Bitmap) extras.get("data");
}
}
}
break;
}
}
private OnClickListener mChooseImage = new OnClickListener() {
#Override
public void onClick(View v) {
try {
// Launch picker to choose photo for selected contact
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", ICON_SIZE);
intent.putExtra("outputY", ICON_SIZE);
intent.putExtra("scale", true);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile()));
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, PHOTO_PICKED);
} catch (ActivityNotFoundException e) {
// LOG THIS
}
}
};
private File getTempFile() {
try {
if (!hasImage) {
FileOutputStream fos = openFileOutput(TEMP_PHOTO_FILE, MODE_WORLD_WRITEABLE);
fos.close();
}
return getFileStreamPath(TEMP_PHOTO_FILE);
} catch (FileNotFoundException e) {
// To be logged later
return null;
} catch (IOException e) {
// To be logged later
return null;
}
}
upon activity result, I set the ImageView's image URI to this file.
When it first completes, the ImageView changes to reflect this. However, if I attempt to choose the image again (same activity), the ImageView will not update until I exit and re-enter the activity. I'm not sure why this happens, is it because I'm trying to write to the temp.jpg everytime? Or do I need to refresh my layout somehow to reflect changes in the ImageView?
Judging by the ImageView source code, the ImageView won't reload the image if you call setImageURI with the same URI. You could try changing the URI by writing your image to another file.
ImageView will not redraw if "new" URI is the same like old one. "View.invalidate()" will not work. To "force" update you can do:
public void onResume() {
super.onResume();
ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
if (hasImage) {
myImageView.setImageDrawable(null); // <--- added to force redraw of ImageView
myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
}
}
invalidate() not worked. Try hack :
imageView.setImageURI(null);
imageView.setImageURI(newUri);
To force redrawing your widget/View just call View.invalidate();
I had a similar problem where I was using the devices camera to take a picture and then wanting the imageView in the original screen to refresh when I returned to it. The solution was to call View.invalidate() in onResume().
For me, it refreshed my ImageView with this
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO && resultCode == RESULT_OK && data != null && data.getData() != null) {
filePath = data.getData();
try {
mProfilePic.setImageURI(null);
mProfilePic.setImageURI(filePath);
Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
mProfilePic.setImageBitmap(imageBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I would suggest this thing solution. After trying lot of solutions i found this one worked for me.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 1000ms
ivProfilePic.setImageBitmap(bitImage);
}
}, 1000);
UIView.transition(with: bannerImageView, duration: 0.3, options: [.transitionCrossDissolve], animations: { [weak self] in
self?.exampleImageView.image = newImage
})
Use this func in your view controller
If you are also setting the image using Glide then check if the url is setting up the image or not. If the Glide fails and sets the error Image then setImageURI won't change the image.
This happened in one of my projects. I though this might help someone.

Categories

Resources