1、启动系统相机
1.1、只是简单的获取所拍照片的缩略图
启动相机
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
获取缩略图
@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);
}
}
1.2、获取所拍的全尺寸照片文件
必须的权限
<
uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE” />
这里的全尺寸是相对于上面的缩略图来讲的,这里为什么需要读取储存的权限呢?因为我们要获取所拍照片的文件的话需要给启动相机的intent传入一个文件以储存所拍的照片,到时候我们读取这个文件就可以了。
如果你APP拍的照片可以让其他应用读写,那么这个文件路径可以用系统公共的图片路径:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
如果你想APP拍的照片只能自己读写,即其他应用和系统相册都无法读写,那么用以下的路径:
getExternalFilesDir(Environment.DIRECTORY_PICTURES);
确定了文件路径,还要保证文件名不能重复:
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
// 唯一的文件名称
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
// File publicDirectory = Environment.getExternalStoragePublicDirectory
// (Environment.DIRECTORY_PICTURES);
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* 文件名前缀 */
".jpg", /* 文件名后缀 */
storageDir /* 路径 */
);
// mCurrentPhotoPath下面会被发送到系统相册里去显示
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
启动相机
static final int REQUEST_TAKE_PHOTO = 2;
private void dispatchTakePictureIntent() {
//action为MediaStore.ACTION_IMAGE_CAPTURE
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// 保存所拍照片的文件
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
//
}
if (photoFile != null) {
//这里为了兼容7.0以下的设备,需要在清单文件中定义一个FileProvider,这里的
//com.jackbear.notificationtimer.fileprovider要和FileProvider中的authorities相同,如下图
Uri photoURI = FileProvider.getUriForFile(this,
"com.jackbear.notificationtimer.fileprovider",
photoFile);
//如果photoFile路径是公共的系统图片路径即通过Environment.getExternalStoragePublicDirectory
//(Environment.DIRECTORY_PICTURES)获取的话则不能用FileProvider的方式了,否则会异常
// Uri photoURI = Uri.fromFile(photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
清单文件中的FileProvider
...
...
上面FileProvider的@xml/file_paths路径为res/xml/file_paths.xml,内容如下:
其中com.jackbear.notificationtime为你的包名,当你获取文件路径传入Environment.DIRECTORY_PICTURES获取的就是上面这个路径。
上面我们用于保存所拍照的文件的路径是通过getExternalFilesDir(Environment.DIRECTORY_PICTURES);获取的,即这个文件是在我们app私有的空间里的,哪怕我们打开系统相册都是无法看到的,那怎样让我们拍摄的照片在系统相册里也能看到呢?
首先,将保存照片的文件路径换为公共的图片路径,即通过以下方式获取:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
其次,通过以下方式将我们的文件路径发送给系统相册:
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//mCurrentPhotoPath即文件的路径
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
显示拍摄的照片
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_TAKE_PHOTO:
//将照片插入系统相册
galleryAddPic();
//显示图片
setPic();
break;
default:
break;
}
}
}
为了避免oom,setPic()函数对照片进行了缩放显示
private void setPic() {
// 获取控件尺寸
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// 获取照片bitmap对象尺寸
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// 计算缩放比例
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// 按缩放比例解析出照片文件
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
1.3、以视频模式启动相机
拍摄视频的话,系统会默认把你APP拍摄的视频插入相册里了。
static final int REQUEST_VIDEO_CAPTURE = 1;
private void dispatchTakeVideoIntent() {
//action为MediaStore.ACTION_VIDEO_CAPTURE
Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
}
}
查看所拍视频
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
Uri videoUri = intent.getData();
mVideoView.setVideoURI(videoUri);
}
}
1.4、在应用市场中仅对有摄像机的设备开放下载
...
在清单文件中声明如上代码表示,仅对有摄像机的设备开放下载,如果不做上述声明的话,当用户安装了你的APP,需要启动相机时,为了更好的用户体验,你可通过下面代码判断当前设备是否有摄像机,从而做对应的处理:
hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)