I have fragments with a circleimageview inside used as a profile image that is saved later in a database correctly.
My problem is to save the state of the imageview with onSaveInstanceState and onPause/onStop to keep their state before saving them in the database and after, for example, performing a screen rotation.
This is my code
public class MyFragment extends Fragment implements View.OnClickListener {
private CircleImageView mPhoto;
private byte[] bytes = null;
private Bitmap photo = null;
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if(bytes!=null) {
outState.putByteArray("bytes", bytes);
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
LayoutInflater lf = getActivity().getLayoutInflater();
view = lf.inflate(R.layout.my_fragment,container,false);
mPhoto = (CircleImageView) view.findViewById(R.id.photo);
view.findViewById(R.id.photo).setOnClickListener(this);
if(savedInstanceState!=null){
if(savedInstanceState.containsKey("bytes")){
bytes = savedInstanceState.getByteArray("bytes");
if(bytes != null) {
//but with a screen rotation the image is not restored
photo = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mPhoto.setImageBitmap(photo);
}
}
}
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.photo:
Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
try {
startActivityForResult(Intent.createChooser(i, "Select Picture"), 0);
}catch (ActivityNotFoundException ex){
ex.printStackTrace();
}
break;
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==0 && resultCode == Activity.RESULT_OK) {
Uri path = data.getData();
Bitmap tmp = null;
try {
tmp = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), path);
} catch (IOException e) {
e.printStackTrace();
}
if(tmp != null) {
mPhoto.setImageBitmap(photo);
bytes = getBitmapAsByteArray(photo);
//tested, bytes is not null and the photo are restored correctly when saved on the database
}
}
}
#Override
public void onResume() {
super.onResume();
bytes = getActivity().getIntent().getByteArrayExtra("bytes");
if(bytes != null) {
//here bytes is null
photo = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mPhoto.setImageBitmap(photo);
}
}
#Override
public void onStop() {
super.onStop();
if(bytes!=null)
getActivity().getIntent().putExtra("bytes",bytes);
}
}
in this way the image is not maintained during a screen rotation, how to correctly implement onsavedInstanceState, onStop and onResume?
Put code before super() method.
#Override
public void onStop() {
if(bytes!=null)
getActivity().getIntent().putExtra("bytes",bytes);
super.onStop();
}
Easiest way Use ViewModel with your fragment.
Refer: https://developer.android.com/topic/libraries/architecture/viewmodel.html
Update:
Step1: Add View Model dependency in build.gradle
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle viewmodel:$lifecycle_version"
Step 2: Create a ViewModel for Fragment
public class MyFragmentViewModel extends ViewModel {
}
Step 3: Set ViewModel in MyFragment
public class MyFragment extends Fragment {
public void onStart() {
MyFragmentViewModel userModel = ViewModelProviders.of(getActivity()).get(MyFragmentViewModel.class);
}
}
Related
I use Navigation component jetpak and in fragment need to get image from gallery.
i use this code:
ActivityResultLauncher<String> mGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
Constants.toast("return!");
imageFile = new File(getRealPathFromURI(uri));
binding.menuFragmentCircularProfileImageview.setImageURI(uri);
}
});
and after fragment attached call mGetContent
binding.menuFragmentCircularProfileImageview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mGetContent.launch("image/*");
// fromGallery();
}
});
So far everything is fine and the gallery opens well.
BUT...
But the selected image does not return.
The app is actually closed.
Where did I do wrong? Or is there another solution?
UPDATED...
this is my fragment:
public class MenuFragment extends Fragment implements LogoutDialog.Listener {
private FragmentMenuBinding binding;
private NavController navController = null;
private UserData userData;
private File imageFile;
private final androidx.activity.result.ActivityResultLauncher<String> getContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(requireActivity().getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
binding.menuFragmentCircularProfileImageview.setImageBitmap(bitmap);
}
});
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
navController = Navigation.findNavController(requireActivity(), R.id.main_activity_nav_host_fragment);
binding = DataBindingUtil.inflate(inflater , R.layout.fragment_menu, container, false);
return binding.getRoot();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
assert getArguments() != null;
userData=MenuFragmentArgs.fromBundle(getArguments()).getUserdata();
operation();
}
private void operation(){
binding.menuFragmentCircularProfileImageview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getContent.launch("image/*");
}
});
}
}
Try using below code:
private ActivityResultLauncher startForResultFromGallery = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK){
try {
if (result.getData() != null){
Uri selectedImageUri = result.getData().getData();
Bitmap bitmap = BitmapFactory.decodeStream(getBaseContext().getContentResolver().openInputStream(selectedImageUri));
// set bitmap to image view here........
binding.menuFragmentCircularProfileImageview.setImageBitmap(bitmap)
}
}catch (Exception exception){
Log.d("TAG",""+exception.getLocalizedMessage());
}
}
}
});
And call above inside your button click like :
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startForResultFromGallery.launch(intent);
You can use this inside your onActivityResult to get the file
InputStream inputStream = requireActivity().contentResolver().openInputStream(uri)
String fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(requireContext().contentResolver().getType(uri))
imageFile = File.createTempFile(UUID.randomUUID().toString(), "." + fileType)
inputStream.copyStreamToFile(file)
I have ported this code from Kotlin let me know if some syntax is wrong.
I believe you have android:noHistory="true" in your AndroidManifest.xml, please remove it, and you should receive the result. I believe the problem has no relation with Jetpack navigation.
I have an activity with a fragment. Inside a fragment I have 2 custom views. A custom view contains an ImageView and a listener. Listener can transform, show a photo in ImageView and upload the photo.
I want to take a photo from camera, return it to the fragment, pass to a view through listener (then show and upload inside the view). Everything works right until the activity is destroyed after camera becomes visible. So, after returning from camera, I restore the fragment, get photo in onActivityResult and try to pass to a view by listener. But a listener is null, and i don't know what view it is attached to.
How can I pass a photo to a view after recreating an activity?
Listener:
public interface Listener {
void onPhotoObtained(#Nullable Uri uri);
}
Custom view:
public class CustomView extends RelativeLayout implements Listener {
#BindView(R.id.imageview) ImageView image;
private PhotoManager photoManager;
public void setPhotoManager(#NonNull PhotoManager photoManager) {
this.photoManager = photoManager;
}
#Override
public void onPhotoObtained(#Nullable Uri uri) {
// transform and show image
}
#OnClick(R.id.imageview)
void onPhotoButtonClicked() {
photoManager.requestPhoto(this);
}
}
Fragment:
public class MainFragment extends Fragment implements PhotoManager {
#BindView(R.id.view1) CustomView view1;
#BindView(R.id.view2) CustomView view2;
// A list of listeners to communicate with custom views.
// When a user clicks an ImageView, this fragment starts a camera to obtain a photo.
private SparseArray<Listener> listeners;
private int lastRequestId;
private Uri uri;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
binder = ButterKnife.bind(this, view);
listeners = new SparseArray<>();
if (savedInstanceState == null) {
lastRequestId = 0;
uri = null;
} else {
lastRequestId = savedInstanceState.getInt(BUNDLE_REQUEST_ID);
uri = savedInstanceState.getParcelable(BUNDLE_KEY_URI);
// How to create a listener list?
}
view1.setPhotoManager(this);
view2.setPhotoManager(this);
return view;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ReceivingPhotoDialogFragment.CAMERA_REQUEST) {
if (resultCode == RESULT_OK) {
if (uri != null) {
// listeners become empty after fragment reinitialization
Listener listener = listeners.get(lastRequestId);
if (listener != null)
listener.onPhotoObtained(uri);
}
}
}
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
bundle.putInt(BUNDLE_REQUEST_ID, lastRequestId);
bundle.putParcelable(BUNDLE_KEY_URI, uri);
super.onSaveInstanceState(outState);
}
#Override
public void requestPhoto(#NonNull Listener listener) {
listeners.put(++lastRequestId, listener);
// Request new photo with lastRequestId
showCamera(lastRequestId);
}
private void showCamera(int requestId) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
uri = null;
if (file != null) {
uri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra(BUNDLE_REQUEST_ID, requestId);
startActivityForResult(intent, CAMERA_REQUEST);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(timeStamp, ".jpg", storageDir);
}
}
A second listener to initialize first:
public interface PhotoManager {
void requestPhoto(#NonNull Listener listener);
}
I still struggle with the activity lifecycle, so this may not be the best answer.
What I do is make my listener as a static variable. This allows the variable to exist in the class instead of the instance of the class which clears when destroyed.
I think, You do not need to re-initialise listener for that,
What you need is add a property named configChanges in your AndroidManifest.xml file for that activity which has this MainFragment
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait"/>
Add these tag configChanges and then run your code.
I want to get data from activity but I keep getting error this error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference.
TrafficActivity.class (Activity)
public class TrafficActivity extends AppCompatActivity {
public static final String FRAGMENT_PDF_RENDERER_BASIC = "pdf_renderer_basic";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_traffic);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_traffic);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(TrafficActivity.this, IpuclariSayfasi.class));
}
});
if (savedInstanceState == null)
{
getFragmentManager().beginTransaction()
.add(R.id.container, new PdfRendererBasicFragment(), FRAGMENT_PDF_RENDERER_BASIC)
.commit();
}
}}
PdfRendererBasicFragment.class(Fragment)
public class PdfRendererBasicFragment extends Fragment implements
View.OnClickListener
{
private static final String O_ANKI_SAYFA_DURUMU = "guncel_sayfa_index";
private ParcelFileDescriptor mFileDescriptor;
private PdfRenderer mPdfRenderer;
private PdfRenderer.Page mGuncelSayfa;
private ImageView mImageView;
private ImageButton mOncekiButon;
private ImageButton mSonrakiButon;
public static String FILENAME;
public PdfRendererBasicFragment()
{
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false);
}
#Override
public void onClick(View view)
{
switch (view.getId()) {
case R.id.onceki: {
//onceki sayfaya geç
showPage(mGuncelSayfa.getIndex() - 1);
break;
}
case R.id.sonraki: {
// sonraki sayfaya geç
showPage(mGuncelSayfa.getIndex() + 1);
break;
}
}
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mImageView = (ImageView) view.findViewById(R.id.pdf_goruntusu);
mOncekiButon = (ImageButton) view.findViewById(R.id.onceki);
mSonrakiButon = (ImageButton) view.findViewById(R.id.sonraki);
mOncekiButon.setOnClickListener(this);
mSonrakiButon.setOnClickListener(this);
int index = 0;
if (null != savedInstanceState) {
index = savedInstanceState.getInt(O_ANKI_SAYFA_DURUMU, 0);
}
showPage(index);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
openRenderer(activity);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(activity, "Beklenmedik hata: " + e.getMessage(), Toast.LENGTH_SHORT).show();
activity.finish();
}
}
#Override
public void onDetach() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onDetach();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mGuncelSayfa) {
outState.putInt(O_ANKI_SAYFA_DURUMU, mGuncelSayfa.getIndex());
}
}
private void openRenderer(Context context) throws IOException
{
// bu ornekte, asset klasöründeki PDF'i okuyoruz.
FILENAME= getArguments().getString("file_name");
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists())
{
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
private void closeRenderer() throws IOException {
if (null != mGuncelSayfa) {
mGuncelSayfa.close();
}
mPdfRenderer.close();
mFileDescriptor.close();
}
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
if (null != mGuncelSayfa) {
mGuncelSayfa.close();
}
mGuncelSayfa = mPdfRenderer.openPage(index);
// ÖNEMLİ: Hedef bitmap ARGB olmalı, RGB olmamalı.
Bitmap bitmap = Bitmap.createBitmap(mGuncelSayfa.getWidth(), mGuncelSayfa.getHeight(),
Bitmap.Config.ARGB_8888);
mGuncelSayfa.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
mImageView.setImageBitmap(bitmap);
sayfayıGuncelle();
}
private void sayfayıGuncelle() {
int index = mGuncelSayfa.getIndex();
int pageCount = mPdfRenderer.getPageCount();
mOncekiButon.setEnabled(0 != index);
mSonrakiButon.setEnabled(index + 1 < pageCount);
getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));
}
public int sayfaSayisiniGetir()
{
return mPdfRenderer.getPageCount();
}
You are setting the argument on the Fragment but calling the Activity
#Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString("file_name", "sample3.pdf");
PdfRendererBasicFragment ff=new PdfRendererBasicFragment();
ff.setArguments(bundle);
startActivity(new Intent(IpuclariSayfasi.this,TrafficActivity.class));
}
And when you really commit the Fragment, you creating a new instance, without any argument:
if (savedInstanceState == null)
{
getFragmentManager().beginTransaction()
.add(R.id.container, new PdfRendererBasicFragment(), FRAGMENT_PDF_RENDERER_BASIC)
.commit();
}
Make the first implementation on the real Fragment call, like this:
if (savedInstanceState == null) {
Bundle bundle = new Bundle();
bundle.putString("file_name", "sample3.pdf");
PdfRendererBasicFragment ff=new PdfRendererBasicFragment();
ff.setArguments(bundle);
getFragmentManager().beginTransaction()
.add(R.id.container, ff, FRAGMENT_PDF_RENDERER_BASIC)
.commit();
}
You have the problem here
FILENAME= getArguments().getString("file_name");
getArguments() is null since you are setting arguments for
PdfRendererBasicFragment ff=new PdfRendererBasicFragment();
ff.setArguments(bundle);
but then you're creating a new Fragment in TrafficActivity.class
.add(R.id.container, new PdfRendererBasicFragment(), FRAGMENT_PDF_RENDERER_BASIC)
and this is the one you're using, but this one does not have any arguments in it
I have an activity which needs to trigger 4 different DialogFragments in which i trigger an intent do get images from camera or gallery.
I can retain the fragment state and continue to observe the "onActivityResult" and send it to the dialogfragmentx but when they recreate and i try to show again the images that i got from the gallery, when i use "addView" on the linearlayout it does nothing.
Here is my code from the activity:
private DFrag_room frag_room;
private DFrag_terrace frag_terrace;
private DFrag_garden frag_garden;
private DFrag_parking frag_parking;
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (frag_room != null) {
getSupportFragmentManager().putFragment(outState, "fragment_room", frag_room);
}
if (frag_terrace != null) {
getSupportFragmentManager().putFragment(outState, "fragment_terrace", frag_terrace);
}
if (frag_garden != null) {
getSupportFragmentManager().putFragment(outState, "fragment_garden", frag_garden);
}
if (frag_parking != null) {
getSupportFragmentManager().putFragment(outState, "fragment_parking", frag_parking);
}
}
#Override
public void onRestoreInstanceState(Bundle inState){
FragmentManager fm = getSupportFragmentManager();
frag_room = (DFrag_room) fm.getFragment(inState, "fragment_room");
frag_terrace = (DFrag_terrace) fm.getFragment(inState, "fragment_terrace");
frag_garden = (DFrag_garden) fm.getFragment(inState, "fragment_garden");
frag_parking = (DFrag_parking) fm.getFragment(inState, "fragment_parking");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (frag_room != null) {
frag_room.onActivityResult(requestCode, resultCode, data);
}
if (frag_terrace != null) {
frag_terrace.onActivityResult(requestCode, resultCode, data);
}
if (frag_garden != null) {
frag_garden.onActivityResult(requestCode, resultCode, data);
}
if (frag_parking != null) {
frag_parking.onActivityResult(requestCode, resultCode, data);
}
}
and the code from one of the dialogfragments (the procedure is the same on every one)
private LinearLayout layout_images;
private ImageView img_add_image;
private File photoFile;
private ArrayList<Uri> images;
public DFrag_room() {
}
public interface DFrag_roomListener {
void onFinishRoom();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dfrag_room, container);
layout_images = (LinearLayout) view.findViewById(R.id.dfrag_room_imgs_layout);
img_add_image = (ImageView) view.findViewById(R.id.dfrag_room_img_add_img);
img_add_image.setOnClickListener(this);
if (savedInstanceState != null) {
images = (ArrayList<Uri>) savedInstanceState.getSerializable("images");
for (int i = 0; i < images.size(); i++) {
addImage(images.get(i));
}
}
setRetainInstance(true);
return view;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation
outState.putSerializable("images", images);
}
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
#Override
public void onActivityResult(int reqCode, int resCode, Intent data) {
switch (reqCode) {
case CONF.REQ_PHOTO:
if (resCode == Activity.RESULT_OK) {
if ((photoFile != null)) {
Uri img = Uri.fromFile(photoFile);
images.add(img);
addImage(img);
}
}
break;
case CONF.REQ_GALLERY:
if (resCode == Activity.RESULT_OK) {
images.add(data.getData());
addImage(data.getData());
}
break;
}
super.onActivityResult(resCode, resCode, data);
}
public void addImage(Uri img_uri) {
int margin = getResources().getDimensionPixelOffset(R.dimen.padding_x_small);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(img_add_image.getWidth(), img_add_image.getHeight());
params.setMargins(0, 0, margin, 0);
RoundedImageView new_img = new RoundedImageView(getActivity());
new_img.setLayoutParams(params);
new_img.setScaleType(ImageView.ScaleType.CENTER_CROP);
new_img.setBackgroundResource(R.drawable.bg_white_stroke);
new_img.setCornerRadius((float) 6);
Glide.with(getActivity()).load(img_uri).thumbnail(0.8f).into(new_img);
layout_images.addView(new_img, 0);
}
When i get the image from the intent it works fine, but when i get it from the saved list of uris (onCreateView) it doesen't work
EDIT:
Sorry, the app doesen't crash, i don't see the image in my layout, it calls "addImage" but i don't see the images.
Solved, i tried to create an imageview with 0 width and 0 height beacusa I create it from the onCreate method where img_add_image.getWidth() is 0.
I am trying to make an app where I can let a user select a picture to display on their profile. I am able to browse and set their selected image on imageview. But the image is lost once the the activity is destroyed. I tried to implement onSaveInstanceState but still it's the same. I'm wondering if I am using it correctly. I hope you can help a newbie like me. Thanks in advance. Here's the code that I'm using:
public class AccountFragment extends Fragment implements OnClickListener {
private LoginDataBaseAdapter loginDataBaseAdapter;
Bitmap image;
Bitmap bitmap;
String picture_location;
TextView textTargetUri;
ImageView targetImage;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_account, container, false);
textTargetUri = (TextView) rootView.findViewById(R.id.targeturi);
targetImage=(ImageView) rootView.findViewById(R.id.profpic);
targetImage.setOnClickListener(new ImageView.OnClickListener(){
#Override
public void onClick(View arg0) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}});
if (savedInstanceState != null) {
//if there is a bundle, use the saved image resource (if one is there)
image = savedInstanceState.getParcelable("BitmapImage");
targetImage.setImageBitmap(image);
textTargetUri.setText(savedInstanceState.getString("path_to_picture"));
}
return rootView;
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putParcelable("BitmapImage", bitmap);
savedInstanceState.putString("path_to_picture", picture_location);
}
#Override
public void onActivityResult( int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK){
Uri targetUri = data.getData();
picture_location = targetUri.toString();
textTargetUri.setText(targetUri.toString());
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(targetUri));
targetImage.setImageBitmap(bitmap);
}
catch (FileNotFoundException e){
e.printStackTrace();
}
}
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}}
By the way, you may have noticed that instead of using the onRestoreInstanceState after oncreate, I tried to use the different approach. I found an answer from another question that you can also implement it inside the oncreate. I used it since whenever I declare the function onRestoreInstanceState I am being asked to remove the #Override annotation.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
image = savedInstanceState.getParcelable("BitmapImage");
targetImage.setImageBitmap(image);
textTargetUri.setText(savedInstanceState.getString("path_to_picture"));
}
Using onSaveInstanceState and onCreate/onRestoreInstanceState is for short term activity state preservation - but not to be used for persistent storage of the application's data.
You can read about onSaveInstanceState here
You can read about persistent storage here
codeMagic suggested using SharedPrefs (see persistent storage link) for your long-term persistent storage. If you wanted to do this, I would suggest saving the image URI (the link has a good example of how to do so) in you onActivityResult method, and then call a method to read the SharedPref and load the image that you can call from onCreate as well as from onActivityResult.
You may also want to store your own copy of the image/bitmap in your application's own internal storage (see persistent storage link).
if you are not finishing the activity, you can use onSavedInstance() to store the picture_location value and bind it back either in onCreate(SavedInst)/onRestore() from the picture_location value.
In case of Bitmaps Instance State is not the suggested way to persist info about the selected image.
You can find the explanation here: Handling configuration Changes
I blogged extensively about it here: Retain selected Image during Screen Rotation
Below I paste my implementation of the illustrated solution:
1 - Create a Fragment and configure it to be retained in memory
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
public class ImageRetainingFragment extends Fragment {
private Bitmap selectedImage;
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
public void setImage(Bitmap selectedImage) {
this.selectedImage = selectedImage;
}
public Bitmap getImage() {
return this.selectedImage;
}
}
2 - Use it in your Activity
private static final String FRAGMENT_NAME = "imageFragment";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
....
initializeImageRetainingFragment();
tryLoadImage();
}
private void initializeImageRetainingFragment() {
// find the retained fragment on activity restarts
FragmentManager fragmentManager = getSupportFragmentManager();
this.imageRetainingFragment = (ImageRetainingFragment) fragmentManager.findFragmentByTag(FRAGMENT_NAME);
// create the fragment and bitmap the first time
if (this.imageRetainingFragment == null) {
this.imageRetainingFragment = new ImageRetainingFragment();
fragmentManager.beginTransaction()
// Add a fragment to the activity state.
.add(this.imageRetainingFragment, FRAGMENT_NAME)
.commit();
}
}
private void tryLoadImage() {
if (this.imageRetainingFragment == null) {
return;
}
Bitmap selectedImage = this.imageRetainingFragment.getImage();
if (selectedImage == null) {
return;
}
ImageView selectedImageView = (ImageView)findViewById(R.id.selectedImage);
selectedImageView.setImageBitmap(selectedImage);
}
1)// manifest.xml
2)//public class MainActivity extends AppCompatActivity implements LocationListener{...
SharedPreferences.Editor editor;
3)//protected void onCreate(Bundle savedInstanceState){ ...
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 3);
}
4)//SHARED PREFERENCES
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", getApplicationContext().MODE_PRIVATE);
editor = pref.edit();
5)//SET IMAGE PATH
if (pref.getString("mydraw", null) != null) {
img6.setImageURI(Uri.parse(pref.getString("mydraw", null)));
} else {
//set default image
img6.setImageResource(R.drawable.poseidon);
}
6)//protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {...
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
img6.setImageURI(data.getData());
//save URI as string
editor.putString("mydraw", data.getData().toString());
editor.commit(); // commit changes
}
}