(二)进阶练习____8、捕捉照片——简易拍照

原文链接:http://docs.eoeandroid.com/training/camera/photobasics.html
翻译:tyutNo4
更新:2012.09.03

目录

 [隐藏

让拍照变得简单

本节课将介绍如何利用系统中已有的照相机应用程序来获取照片。

假设你现在正在做一个由普通大众提供信息来源的气象服务,这个服务会把通过客户应用程序拍摄的照片组织到一起做成一张全球性的气象地图。集成拍摄照片功能只是应用程序的很小的一部分,你肯定只想花费很小的精力,而不是花大力气重新开发一个相机。幸运的是大多数Android设备都已经安装至少一个照相机应用程序。在这节课中,你将学到如何利用已经安装的照相机来进行拍照。 

请求拍照权限

如果拍照是你应用程序的一项基本功能,在Google Play上会限制她的可见性。你的应用程序依赖照相机的话需要在manifest文件中添加 <uses-feature> 标签: 

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

如果你的应用程序中添加了以上代码而又不需要照相机这个功能的话,你可以在<uses-feature> 标签中添加android:required="false" 属性。如果你这么做了的话,Google Play将会允许那么没有照相机的设备下载你的应用程序,但是之后会在运行过程中通过调用hasSystemFeature(PackageManager.FEATURE_CAMERA)代码来验证照相机是否可用。这个时候如果没有相机可用的话,你应该禁用你的相机功能。

利用照相机来拍照

Android授权给其他应用程序是通过调用一个描述该怎么做的Intent来实现的。这个过程包括三部分:Intent、一个开启另外一个Activity的调用和一些处理影像数据的代码(当焦点返回到你当前Activity的时候)。 下面是一个调用intent来实现拍照的方法: 

private void dispatchTakePictureIntent(int actionCode) {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    startActivityForResult(takePictureIntent, actionCode);
}

恭喜你:通过以上代码你的应用程序就能够让照相程序执行自己的命令来拍照了。当然如果没有一个兼容的应用程序来接受你发出的intent,你的应用程序将会失败就像一个办砸了的跳水表演。下面是一个检查有没有个一个应用程序来接受处理你发出的intent的方法:

public static boolean isIntentAvailable(Context context, String action) {
    final PackageManager packageManager = context.getPackageManager();
    final Intent intent = new Intent(action);
    List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

查看照片

当然如果你不满足于只是简单的拍照的话,你可能想拍完照之后马上看看效果然后再做点别的。 Android照相机会把照片进行编码,然后保存到返回数据的Intent,这个Intent会传递给onActivityResult() ,照片会以Bitmap的形式,主键为"data"保存在extras中。下面的这段代从ImageView中码检索并显示照片: 

private void handleSmallCameraPhoto(Intent intent) {
    Bundle extras = intent.getExtras();
    mImageBitmap = (Bitmap) extras.get("data");
    mImageView.setImageBitmap(mImageBitmap);
}

提示:"data"中取得的缩略图可能作为图标比较合适,如果要处理全尺寸照片的话还需要做很多。

保存照片

如果你给拍摄的照片一个保存的文件的话,Android照相程序会保存一个全尺寸的照片。但是你必须提供一个包含存储卷、文件夹和文件名称的路径。 下面是一个非常简单的取得路径的方式,但是需要Android2.2(API level 8)或者更高的版本。 

storageDir = new File(
    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), 
    getAlbumName()
);

对于低版本的API levels,你只得自己提供照片文件夹的名称了: 

storageDir = new File (
    Environment.getExternalStorageDirectory()
        + PICTURES_DIR
        + getAlbumName()
);

提示:上面路径中的PICTURES_DIR部分是指 Pictures/ ,用来在外部/共享设备上分享照片的标准路径。

设置文件的名称

就像上一部分说的那样,保存图片的文件位置需要由设备环境提供,而我们需要做的就是选择一个健壮性的文件命名方案,你肯定希望保存路径是以成员变量的形式。下面是一个实例解决方案: 

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
    File image = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, getAlbumDir());
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

在intent上追加文件名

一旦你确定了一个保存图片的文件路径,就通过intent把保存位置传递给照相机程序。 

File f = createImageFile();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));

添加照片到图片库

当你通过intent得到了一张照片的时候,你应该想知道这个照片位于哪里。因为你说过第一次应该保存在哪里。对其他人来说最简单的访问你的照片的方式就是让他通过系统的Media Provider来访问。 下面的一个例子演示了如何调用系统的媒体扫描器来把你的照片添加到Media Provider库中,并且让它在Android Gallery 应用程序及其他一些应用程序中可用: 

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);
}

解码缩略图

由于有限的内存,要处理多张全尺寸的照片会非常复杂,如果你发现你的应用程序从内存中溢出了在仅仅显示了几张照片的时候,你可以大量地减少动态堆的数据,通过扩展JPEG到内存数组(里面有你想要的全尺寸照片对应的缩略图)中,下面的例子演示了这种技巧:

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);
}

 

 
posted @ 2014-07-30 16:45  ╰→劉じ尛鶴  阅读(163)  评论(0)    收藏  举报