Android-拍照获取缩略图以及完整图片(适配androidN)

2017/10/24 posted in  Android

调用系统相机拍照获取缩照片略图

调用系统相机拍照时,如果不传路径,图片默认返回缩略图,不需要权限

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}

takePictureIntent.resolveActivity(getPackageManager()) != null

在官方文档中有描述:startActivityForResult()方法受到调用resolveActivity()的条件的保护,该方法返回可处理该意图的第一个活动组件,执行此检查很重要,因为如果您使用没有应用程序可以处理的意图调用startActivityForResult(),则您的应用程序将崩溃。所以只要结果不为空,就可以安全的使用意图,大概意思是检测手机中有没有相机。

另外一种检测相机的方法是

<manifest ... >
    <uses-feature android:name="android.hardware.camera"
                  android:required="true" />
    ...
</manifest>

required=true表示要安装该应用,手机必须有摄像头该硬件。要不然不允许安装

处理回调

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bundle extras = data.getExtras();
        Bitmap imageBitmap = (Bitmap) extras.get("data");
        mImageView.setImageBitmap(imageBitmap);
    }
}

调用系统相机拍照获取全尺寸照片

如果要保存一个全尺寸的照片,必须提供一个完整的文件名,当照片需要保存到公有目录时,那么需要一个写入的权限(写入权限已经隐含的允许读取[READ_EXTERNAL_STORAGE],这样子就可以将app拍的照片写入到外部存储,该外部存储的链接是getExternalStoragePublicDirectory()

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

当需要将得到的照片保存到私有目录时,使用该链接getExternalFilesDir(),getFilesDir(),这两个目录下的文件在应用删除的时候就自动删掉了,在android4.4以下需要权限,4.4以上应用之间不能被其他程序访问,因此该权限只要在4.4以下加入

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
    ...
</manifest>
  • 提供一个不会冲突的文件名,例如按时间来起名
String mCurrentPhotoPath;

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
        imageFileName,  /* prefix */
        ".jpg",         /* suffix */
        storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}
  • 构造拍照intent,适配7.0以及4.0
static final int REQUEST_TAKE_PHOTO = 1;

    private void camera2() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;

            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                // Error occurred while creating the File
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(this,
                        "lsp.com.ipctest.fileprovider",
                        photoFile);

                //解决4.0
                List<ResolveInfo> resInfoList = getPackageManager()
                        .queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
                for (ResolveInfo resolveInfo : resInfoList) {
                    String packageName = resolveInfo.activityInfo.packageName;
                    grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }


                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }
    }

FileProvider.getUriForFile()用来返回一个content:// URI。对于最新的针对Android 7.0(API级别24)的应用程序,通过一个包边界传递一个文件:// URI会导致FileUriExposedException
鸿洋的博客关于android7.0 以及 4.0 拍照封装的处理(点击跳转)

  • 取得结果
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
    Bitmap imageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
    Log.e(TAG, "文件大小" + imageBitmap.getByteCount() / 1024 + "kb");
    ((ImageView) findViewById(R.id.img)).setImageBitmap(imageBitmap);
}
  • 将照片保存到相册如果你保存图片的路径是getExternalFilesDir() 媒体扫描器访问不到,只有你自己的应用可以访问,因此一下方法可以将图片保存到相册
private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}