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

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

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

1
2
3
4
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(),则您的应用程序将崩溃。所以只要结果不为空,就可以安全的使用意图,大概意思是检测手机中有没有相机。

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

1
2
3
4
5
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true" />
...
</manifest>

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

处理回调

1
2
3
4
5
6
7
8
@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()

1
2
3
4
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>

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

1
2
3
4
5
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest>
  • 提供一个不会冲突的文件名,例如按时间来起名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 拍照封装的处理(点击跳转)

  • 取得结果
1
2
3
4
5
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() 媒体扫描器访问不到,只有你自己的应用可以访问,因此一下方法可以将图片保存到相册
1
2
3
4
5
6
7
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);
}