显示 Android 中相机拍摄的画中画视图图片

Displaying picture in image view picture taken by Camera in Android

我正在尝试以下操作:

  1. 用我的 Android 设备拍照。
  2. 使用步骤 # 1 中拍摄的照片填充图像视图

我已尝试按照下面列出的教程进行操作

  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

但似乎没有任何效果。这是我的代码

缩小布局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>

我将此布局加载到一个片段中。这是我的片段代码。

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);
    }
}

我的Android清单

<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 个文件

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

更新:我添加了屏幕截图。

我应该指定,但是当我尝试这个时,控件根本没有 return onActivityResult。我不知道。

图片 # 1:getActivity().startActivityForResult(captureImage, REQUEST_CAMERA) 为 returned

时的视图

我通过单击相机图标然后按返回键拍照。控件永远不会转到 onActivityResult。我不知道为什么会这样。我尝试了设备和模拟器,并且始终得到相同的结果。当我再次点击按钮时,我看到如下崩溃。

.

异常堆栈跟踪如下:

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)

更新#2:拍照后相机不会像

一样return到onActivityResult
  1. Camera does not return to OnActivityResult

更新

这是对我有用的解决方案

  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();
}
}

在 XML 中:

<ImageView
    android:id="@+id/profilePic"
    android:layout_width="@dimen/sdp105"
    android:layout_height="@dimen/sdp105"
    android:layout_centerHorizontal="true"
    android:background="@drawable/border"
    android:src="@drawable/ic_profile" />

<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" /> 

在片段中:

public class CrimeFragment extends Fragment {

    ImageView profilePic;
    ImageButton mPhotoButton;
    private final int PICK_IMAGE_CAMERA = 1, PICK_IMAGE_GALLERY = 2;
    public Bitmap bitmap;
    private Uri filePath;

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

    profilePic = view.findViewById ( R.id.profilePic );
    mPhotoButton = view.findViewById(R.id.crime_camera);


    mPhotoButton.setOnClickListener ( new View.OnClickListener () {
                @Override
                public void onClick(View view) {
                    changeProfileImage ();
                }
            } );
return view;
}


    private void changeProfileImage() {
            try {
                PackageManager pm = getPackageManager ();
                int hasPerm = pm.checkPermission ( Manifest.permission.CAMERA, getPackageName () );
                if (hasPerm == PackageManager.PERMISSION_GRANTED) {
                    final CharSequence[] options = {"Take Photo", "Choose From Gallery", "Cancel"};
                    android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder ( RegisterActivity.this );
                    builder.setTitle ( "Select Option" );
                    builder.setItems ( options, new DialogInterface.OnClickListener () {
                        @Override
                        public void onClick(DialogInterface dialog, int item) {
                            if (options[item].equals ( "Take Photo" )) {
                                dialog.dismiss ();
                                Intent intent = new Intent ( MediaStore.ACTION_IMAGE_CAPTURE );
                                startActivityForResult ( intent, PICK_IMAGE_CAMERA );
                            } else if (options[item].equals ( "Choose From Gallery" )) {
                                dialog.dismiss ();
                                Intent pickPhoto = new Intent ( Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI );
                                startActivityForResult ( pickPhoto, PICK_IMAGE_GALLERY );
                            } else if (options[item].equals ( "Cancel" )) {
                                dialog.dismiss ();
                            }
                        }
                    } );
                    builder.show ();
                } else Toast.makeText ( this, "Camera Permission error", Toast.LENGTH_SHORT ).show ();
            } catch (Exception e) {
                Toast.makeText ( this, "Camera Permission error", Toast.LENGTH_SHORT ).show ();
                e.printStackTrace ();
            }
        }

}



 @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult ( requestCode, resultCode, data );
            if (requestCode == PICK_IMAGE_CAMERA) {
                try {
                    bitmap = (Bitmap) data.getExtras ().get ( "data" );
                    profilePic.setImageBitmap ( bitmap );
                } catch (Exception e) {
                    e.printStackTrace ();
                }
            } else if (requestCode == PICK_IMAGE_GALLERY) {
                filePath = data.getData ();
                try {
                     if(data!=null)
                     { // user selects some Image
                        filePath = data.getData();
                        if (filePath != null) {
                        bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
                        profilePic.setImageBitmap(bitmap);
                     }
                   }
                   else
                   { // user simply backpressed from gallery
                   }
                } catch (IOException e) {
                    e.printStackTrace ();
                }
            }
        }

就用这个class。您可以获得许可并获取图像并将其显示在图像视图中。 如果需要任何帮助,请回复评论谢谢。

 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;
        }

    }

}

在清单文件中添加这个

  <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" />