轻松的拍照
hasSystemFeature(PackageManager.FEATURE_CAMERA).
用一个相机APP来照相
上面那段代码,标注的那个位置,开发的时候看不懂,于是去翻了官方的文档。
给所有有照相功能的APP发去一个照相并返回数据的Intent.
调用者可以传入一个EXTRA_OUTPUT的extra,用来控制图片存储位置。如果这个EXTRA_OUTPUT不存在的话,小尺寸的图片将会以Bitmap对象,放到extra里返回。这对于那种只需要小图片的应用来说很爽。如果EXTRA_OUTPUT存在的话,全尺寸图片将会存在EXTRA_OUT的URI值所写的位置。(官方文档后面还有两句话是关于版本不同的,我就不翻译了)
这个教程可以教你如何用一个已经安装的相机APP来拍照
首先来请求一个相机权限
如果拍照这个功能在你的应用里是很核心的功能,那么你可以在商店里要求用户的设备必须要有摄像头才能下载安装,你只需要在你的Manifest文件里加入下面几行代码就可以了:
<manifest ... > <uses-feature android:name="android.hardware.camera" android:required="true" /> ... </manifest>
同时你可以用代码来检测设备是不是具有摄像头:
hasSystemFeature(PackageManager.FEATURE_CAMERA);
Android请求使用其他APP一般是用Intent对象,并在这个对象里描述你的要求。
下面这段程序进行了三个工作:实例化了一个Intent,激活了外部的一个Activity,并且写了一些代码,用于当焦点返回这个Activity时,处理图片数据。
这是一段拍照的function:
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); } }
注意这个startActivityForResult()方法,这个方法如果你调用了一个Intent但是没有APP能够响应(比如你的手机里没有可以照相的软件)那么程序就会崩溃,为了安全起见,可以用这个resolvActivity()保护它,代码就可以像上面那样写,具体的东西就不深入挖掘了,毕竟是为了更快的写出照相功能。
得到缩略图
如果这种简单的功能无法满足你应用的需求——你可能需要把拍到的照片先处理一下。
安卓照相应用把图片编码以后转成Bitmap对象放到extras里,然后提交到onActivityResult(),在Intent的data键下。
@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); } }
注意:这个从data返回的缩略图可能适合当一个图标,但是它除了当图标也不能当别的了。因为太小了。。如果想处理大图的话,我们需要一些其他的工作。
搞定大图!
getExternalStoragePublicDirectory()
, 方法的DIRECTORY_PICTURES
属性来获取这个存储区的路径。
READ_EXTERNAL_STORAGE
和 WRITE_EXTERNAL_STORAGE
权限。
<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>不过如果你不想存储到公共区,想存储到你的自己的应用专属空间,你可以用这个方法:
getExternalFilesDir()
.
maxSdkVersion
:
<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" /> ... </manifest>注意:当你使用
getExternalFilesDir()
.的时候,里面存储的照片会随着你卸载应用而被删除。
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 = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = "file:" + image.getAbsolutePath(); return image; }用这个方法可以为你创建一个图片文件,现在你可以创建或者调用一个Intent了,就像这样:
static final int REQUEST_TAKE_PHOTO = 1; private void dispatchTakePictureIntent() { 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) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); } } }这里补充一句:MediaStore.EXTRA_OUTPUT这个字段在官网的说明是:
把照片加入相册
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); }
处理文件缩放
private void setPic() { // Get the dimensions of the View int targetW = mImageView.getWidth(); int targetH = mImageView.getHeight(); // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image int scaleFactor = Math.min(photoW/targetW, photoH/targetH); // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); mImageView.setImageBitmap(bitmap); }