请求摄像头权限
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true" />
...
</manifest>
谷歌Play将允许在没有摄像头的设备下载应用程序。那么您有责任通过调用在运行时检查相机的可用性hasSystemFeature(PackageManager.FEATURE_CAMERA)。如果摄像机无法使用,则应禁用相机功能。
打开拍照应用拍照
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent(){
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
//禁用相关东西
}else {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(getPackageManager())!= null){
startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
}
}
}
注意:在调用startActivityForResult()方法之前,先调用resolveActivity(),这个方法能检查有没有能处理这个Intent的activity。只是这个检查非常有必要,因为如果你调用startActivityForResult()时,没有app能处理你的Intent,你的app就会crash。所以只要返回不为null,触发Intent就是安全的。
获取缩略图
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode==REQUEST_IMAGE_CAPTURE&&resultCode==RESULT_OK){
Bundle extras = data.getExtras();
//date对应的就是拍照的图片
Bitmap imageBitmap = (Bitmap) extras.get("date");
mimageView.setImageBitmap(imageBitmap);
}
}
注意:获取的图片是略缩图。由于兼容性问题有些手机可能不能正常显示,所以可以通过文件方式保存并处理。
保存全尺寸图片
一般情况下,用户与设备照相机拍摄的图片应在公共的外部存储,使他们可以被所有应用访问。
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
但是,如果你想将照片保持私密只有您的应用程序,你可以改用所提供的目录getExternalFilesDir()。在Android 4.3以下,写这个目录也需要 WRITE_EXTERNAL_STORAGE许可。与Android 4.4开始,许可不再需要因为该目录是不能被其他应用程序访问,所以你可以声明权限只能通过添加较低Android版本的请求maxSdkVersion属性
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest>
一旦你决定在目录中的文件,你需要创建抗冲突的文件名。你也不妨来保存以备后用一个成员变量的路径。下面是对于使用日期时间戳新照片返回唯一的文件名的方法的例子的解决方案:
private File createImageFile() throws IOException{
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* 前缀 */
".jpg", /* 后缀 */
storageDir /* 目录 */
);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
由于使用文件获取现在的Intent应该是这样的
static final int REQUEST_TAKE_PHOTO = 1;
private void dispatchTakePictureIntent(){
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
//禁用相关东西
}else {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(getPackageManager())!= null){
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if(photoFile!=null){
Uri photoURI = FileProvider
.getUriForFile(this,"com.example.android.fileprovider",photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,photoURI);
startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
}
}
}
}
以及FileProvider的相关配置
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
...
</application>
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>
关于FileProvider请查阅 android学习(十二) 分享文件 FileProvider
将图片添加到图库里
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);
}
注意:如果你保存的图片是通过getExternalFilesDir()保存的则图库是无法获取的,因为这是私人目录。
解析图像
这仅仅是一个例子
private void srtPic(){
//获取视图的维度
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);
}
注意bitmap和view的大小,如果获取的图片小于view则会报错。