In my Fragment
I try to take picture from my camera but the onActivityResult
of my Fragment
is not called. After taking photo this Fragment
is not showing and is switching to my first Fragment
. In there any other way for capturing photos in a Fragment
, or what am I doing wrong?
Here is my current code:
public void takePhoto() { Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); File photo = new File(Environment.getExternalStorageDirectory(), "Pic.jpg"); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); imageUri = Uri.fromFile(photo); PhotosListFragment.this.startActivityForResult(intent, 100); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 100: if (resultCode == Activity.RESULT_OK) { Uri selectedImage = imageUri; getActivity().getContentResolver().notifyChange(selectedImage, null); ContentResolver cr = getActivity().getContentResolver(); Bitmap bitmap; try { bitmap = android.provider.MediaStore.Images.Media .getBitmap(cr, selectedImage); viewHolder.imageView.setImageBitmap(bitmap); Toast.makeText(getActivity(), selectedImage.toString(), Toast.LENGTH_LONG).show(); } catch (Exception e) { Toast.makeText(getActivity(), "Failed to load", Toast.LENGTH_SHORT) .show(); Log.e("Camera", e.toString()); } } } }
This is done as follows: Intent camera_intent = new Intent(MediaStore. ACTION_IMAGE_CAPTURE); startActivityForResult(camera_intent, pic_id); Now use the onActivityResult() method to get the result, here is the captured image.
onActivityResult , startActivityForResult , requestPermissions , and onRequestPermissionsResult are deprecated on androidx.
Just click on button present in the toolbar of Android Studio. Select your emulator. Now, your camera app is ready and displayed by the emulator. Now, when you click on camera in the app, your camera will start.
Modify src/MainActivity. java file to add intent code to launch the Camera. Add the Camera permission and run the application and choose a running android device and install the application on it and verify the results. Following is the content of the modified main activity file src/MainActivity.
Hope this will help you:
public class CameraImage extends Fragment { private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1888; Button button; ImageView imageView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.camera_image, container, false); button = (Button) rootView.findViewById(R.id.button); imageView = (ImageView) rootView.findViewById(R.id.imageview); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE); } }); return rootView; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { Bitmap bmp = (Bitmap) data.getExtras().get("data"); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); // convert byte array to Bitmap Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); imageView.setImageBitmap(bitmap); } } } }
This is one of the most popular issue. We can found lots of thread regarding this issue. But none of them is useful for ME.
So I have solved this problem using this solution.
Let's first understand why this is happening.
We can call startActivityForResult
directly from Fragment but actually mechanic behind are all handled by Activity.
Once you call startActivityForResult
from a Fragment, requestCode will be changed to attach Fragment's identity to the code. That will let Activity be able to track back that who send this request once result is received.
Once Activity was navigated back, the result will be sent to Activity's onActivityResult with the modified requestCode which will be decoded to original requestCode + Fragment's identity. After that, Activity will send the Activity Result to that Fragment through onActivityResult. And it's all done.
The problem is:
Activity could send the result to only the Fragment that has been attached directly to Activity but not the nested one. That's the reason why onActivityResult of nested fragment would never been called no matter what.
Solution:
1) Start Camera Intent in your Fragment by below code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Fragment frag = this; /** Pass your fragment reference **/ frag.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); // REQUEST_IMAGE_CAPTURE = 12345
2) Now in your Parent Activity override **onActivityResult()
:**
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
You have to call this in parent activity to make it work.
3) In your fragment call:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == REQUEST_IMAGE_CAPTURE) { // Do something with imagePath Bitmap photo = (Bitmap) data.getExtras().get("data"); imageview.setImageBitmap(photo); // CALL THIS METHOD TO GET THE URI FROM THE BITMAP Uri selectedImage = getImageUri(getActivity(), photo); String realPath=getRealPathFromURI(selectedImage); selectedImage = Uri.parse(realPath); } } }
4) Reference methods for getting URI:
-> Method for getting Uri from the Bitmap
public Uri getImageUri(Context inContext, Bitmap inImage) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes); String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null); return Uri.parse(path); }
-> Method for getting File path from the Uri
public String getRealPathFromURI(Uri contentUri) { Cursor cursor = null; try { String[] proj = { MediaStore.Images.Media.DATA }; cursor = getActivity().getContentResolver().query(contentUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } finally { if (cursor != null) { cursor.close(); } } }
That's it. With this solution, it could be applied for any single fragment whether it is nested or not. And yes, it also covers all the case! Moreover, the codes are also nice and clean.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With