androidimageviewandroid-photoview

Displaying picture in image view picture taken by Camera in Android


I am trying to attempt the following:

  1. Take the picture with my Android device.
  2. Populate the Image View with the picture taken in step # 1

I have tried to follow the tutorials listed below

  1. https://developer.android.com/training/camera/photobasics
  2. How to display picture in imageview photo taken by camera in android
  3. display picture in imageview photo taken by camera in android

But nothing seems to work. Here is my code

Reduced Layout xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp">
      <ImageView
                android:id="@+id/crime_photo"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:background="@android:color/darker_gray"
                android:contentDescription="@string/show_a_picture"
                android:cropToPadding="true"
                android:scaleType="centerInside" />

      <ImageButton
                android:id="@+id/crime_camera"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:contentDescription="@string/take_a_picture"
                android:src="@android:drawable/ic_menu_camera" />
</LinearLayout>

I load this layout inside a fragment. Here is my fragment code.

public class CrimeFragment extends Fragment {

  private static final String TAG = CrimeFragment.class.getName();


    private ImageView mPhotoView;

    private ImageButton mPhotoButton;

    private File mPhotoFile;

    private String mPhotoPath;

    private static final String ARG_ID = "crime_id";

    static final String DIALOG_PHOTO = "DialogPhoto";

    static final int REQUEST_CAMERA = 3;

    static final int REQUEST_PHOTO = 4;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState)  {
        View view = inflater.inflate(R.layout.fragment_crime, container, false);

        PackageManager packageManager = getActivity().getPackageManager();
    mPhotoButton = (ImageButton) view.findViewById(R.id.crime_camera);
    mPhotoButton.setEnabled(packageManager.hasSystemFeature(
          PackageManager.FEATURE_CAMERA_ANY));

    final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            mPhotoButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
 mPhotoPath = mCrime.getPhotoFilePath();
              mPhotoFile = createTempFile(mPhotoPath);
              CrimeLab.get(getActivity()).updateCrime(mCrime);
              if (mPhotoFile!= null) {
                Uri uri = FileProvider.getUriForFile(getActivity(),
                    "com.myproject.criminalintent.fileprovider", mPhotoFile);
                captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                getActivity().startActivityForResult(captureImage, REQUEST_CAMERA);
              }
            });

// Populate the image view if it exists.
mPhotoView = view.findViewById(R.id.crime_photo);
mPhotoView.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
     updatePhotoView();

  }
});

        return view;
    }

private void updatePhotoView() {
    mPhotoPath = mCrime.getPhotoFilePath();

    if (mPhotoPath == null) {
        mPhotoFile = createTempFile(mCrime.getPhotoFilename());
        mPhotoPath = mPhotoFile.getAbsolutePath();
        mCrime.setPhotoFilePath(mPhotoPath);
        CrimeLab.get(getActivity()).updateCrime(mCrime);

      mPhotoView.setImageDrawable(null);
    } else {
        // Get photo from the gallery to populate the image view.
      if (mPhotoFile == null || !mPhotoFile.exists()) {
        mPhotoFile = createTempFile(mCrime.getPhotoFilename());
      }
      Bitmap bitmap = PictureUtils.getScaledBitmap(mPhotoFile.getAbsolutePath(), getActivity());
      if (bitmap != null) {
        mPhotoView.setImageBitmap(bitmap);
      }
    }

private File createTempFile(String path) {
      try {
        File storageDirectory = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(path, ".jpg", storageDirectory);
      } catch (IOException ioe) {
        Log.e(TAG, "Unable to create temp file : " + mPhotoFile, ioe);
        return null;
      }
    }

  @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != Activity.RESULT_OK ) {
        return;
    }
    if (requestCode == REQUEST_CAMERA) {
      Bundle extras = data.getExtras();
      Bitmap imageBitmap = (Bitmap) extras.get("data");
      mPhotoView.setImageBitmap(imageBitmap);
    }
}

My Android Manifest

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.myproject.criminalintent.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
        <meta-data android:resource="@xml/files" android:name="android.support.FILE_PROVIDER_PATHS"/>
        </provider>

XML Files

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="crime_photos"  path="Android/data/com.myproject.criminalintent/files/Pictures" />
</paths>

Update: I have added screen shots.

I should have specified, but when I try this the control does not return onActivityResult at all. I don't know.

Image # 1: The view when the getActivity().startActivityForResult(captureImage, REQUEST_CAMERA) is returned

Camera view on an emulator

I take a picture by clicking on the camera icon and then pressing the back key. The control never goes to onActivityResult. I don't know why that is the case. I tried the device and the emulator, and I consistently get the same result. When I click on button again, I see a crash as follows.

Camera Crash.

The exception stack trace is as follows:

java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.myproject.criminalintent.fileprovider/crime_photos/IMG_d5d15282-9ac9-4a8d-adea-0ba59d8db7d31012669679698977960.jpg from pid=7201, uid=10074 requires the provider be exported, or grantUriPermission()
        at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:706)
        at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:515)
        at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:487)
        at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:385)
        at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
        at android.os.Binder.execTransact(Binder.java:731)

Updated # 2: The camera does not return to onActivityResult after the picture has been taken just like

  1. Camera does not return to OnActivityResult

Update

This is the solution that worked for me

  private void updatePhotoview() {
    if (mPhotoPath == null) {
      mPhotoPath = mCrime.getPhotoFilePath();
    }
    if (mPhotoPath == null) {
      return;
    }
    final Uri uri = Uri.parse("file://" + mPhotoPath);
    final ViewTreeObserver vo = mPhotoView.getViewTreeObserver();
    vo.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
        int finalHeight = mPhotoView.getMeasuredHeight();
        int finalWidth = mPhotoView.getMeasuredWidth();
        Bitmap bitmap = PictureUtils.getScaledBitmap(uri, finalHeight, finalWidth, getActivity());
        mPhotoView.setImageBitmap(bitmap);
        CrimeLab.get(getActivity()).updateCrime(mCrime);
        if (Util.isOsVersionGreaterOrEqualTo(Build.VERSION_CODES.JELLY_BEAN)) {
          mPhotoView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
      }
    });
  }


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {
  return;
}
if (requestCode == REQUEST_CAMERA) {
   updatePhotoview();
}
}

Solution

  • Just use this class. You can get permission and get image and show it in imageview. If need any help reply with comment thanks.

     public class CameraFragment extends android.support.v4.app.Fragment  {
    
        private String imageFilePath;
        private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
        private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
        private String visitingCard;
        private ImageView visitingCardImage;
    
        public CameraFragment() {
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            setHasOptionsMenu(true);
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    
            View view = inflater.inflate(R.layout.fragment_fragment_camera, container, false);
    
            if(checkPermission()){
                openCameraIntent();
            }
    
            visitingCardImage = view.findViewById(R.id.crime_photo);
            return view;
        }
    
        public static String getBase64String(Bitmap image) {
            String encodeString = null;
            try {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                image.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
                byte[] byteArray = byteArrayOutputStream.toByteArray();
                encodeString = Base64.encodeToString(byteArray, Base64.DEFAULT);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return encodeString;
        }
    
    
    
    
        BitmapFactory.Options options;
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            //getActivity();
            String compressedPath = null;
            if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE && resultCode == RESULT_OK) {
                try {
                    ImageCompressor compressor = new ImageCompressor();
                    compressedPath = compressor.compressImage(imageFilePath, getActivity());
                    Bitmap bitmap = BitmapFactory.decodeFile(compressedPath);
                    visitingCardImage.setImageBitmap(bitmap);
                    visitingCard = getBase64String(bitmap);
                } catch (OutOfMemoryError e) {
                    try {
                        options = new BitmapFactory.Options();
                        options.inSampleSize = 2;
                        Bitmap bitmap =  BitmapFactory.decodeFile(compressedPath, options);
                        visitingCardImage.setImageBitmap(bitmap);
                        visitingCard = getBase64String(bitmap);
                        //return bitmap;
                    } catch(Exception el) {
                        el.printStackTrace();
                    }
                }
    
            } else {
                Toast.makeText(getActivity(), "cancelled image capture", Toast.LENGTH_SHORT).show();
            }
    
        }
    
        private void openCameraIntent() {
            Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (pictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
                File photoFile;
                try {
                    photoFile = createImageFile();
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
                Uri photoUri;
                if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
                    photoUri = Uri.fromFile(photoFile);
                } else {
                    photoUri = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".provider", photoFile);
                }
                pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                startActivityForResult(pictureIntent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
                if (grantResults.length <= 0) {
                    Log.i(TAG, "User interaction was cancelled.");
                }else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openCameraIntent();
                }
            }
        }
        //endregion
    
        private File createImageFile() throws IOException {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
            String imageFileName = "IMG_" + timeStamp + "_";
            File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            File image = File.createTempFile(imageFileName, ".jpg", storageDir);
            imageFilePath = image.getAbsolutePath();
            return image;
        }
    
        private boolean checkPermission() {
    
            if (Build.VERSION.SDK_INT >= 23) {
                if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
                        && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                    return true;
                } else {
                    requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSIONS_REQUEST_CODE);
                    return false;
                }
            } else {
                return true;
            }
    
        }
    
    }
    

    In manifest file add this

      <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />