这个课程说明如何使用一个已存在的相机程序来捕捉照片

假设你实现了一个众包的天气服务,它让一个全球的天气地图和由设备运行你的客户端程序拍摄的天空照片结合。结合照片仅仅是你的应用程序的一小部分。你想拍照用最小的烦恼,不重新开发照相机。幸运的是,大多数Android设备已经按照了至少一个照相机应用程序。在这个课程,你将会学习如何使用它给你拍照片。

请求照相机权限

————————————————————————————————————————————————————————————————

如果你的应用程序的基本功能是拍照,然后再GooglePlay对于有照相机的设备限制它的可见性。为了告知你的应用程序基于一个相机,在你的清单文件中放置一个<uses-feature>标识

<manifest ... >    <uses-feature android:name="android.hardware.camera" />    ... </manifest ... > 
如果你的应用程序使用,但是为了运行不要求一个相机,在标签中添加android:required=”false”。在这种情况下,GooglePlay将允许没有照相机的设备下载你的应用程序。这是你的职责,通过调用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中编码这个相片,作为一个小的位图附件分发给onActivityResult()方法。在“data”关键字之下。下面的代码获取这个照片,并在一个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级别,你必须自己提供相片目录的名字

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创建一个照片的时候,你应该知道你的照片被放在什么位置,因为你说了在哪里首先保存它。对于其它人,可能更早使你的照片可访问的方式是,使它系统的MediaProvider可访问

下面例子方法演示了如何调用系统的媒体扫描器来将你的照片添加到MediaProvider的数据库中,使它在Android的画廊应用程序和其它应用程序中有效

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

更多相关文章

  1. 第三部分:Android(安卓)应用程序接口指南---第三节:应用程序资源--
  2. andorid ANR keyDispatchingTimedOut的原因和解决之道
  3. Android(安卓)应用程序向低版本兼容的问题
  4. Android应用程序之数据存储(一)
  5. 帮助android程序实现动画特效--Lemon动画库
  6. [置顶] 那两年炼就的Android内功修养
  7. Android应用程序签名过程分析
  8. OpenCV: 使用C和C++开发到底哪个好?
  9. Android系统的Root权限获取与检测

随机推荐

  1. NoSQL Memcached
  2. 2018年5大微服务发展趋势
  3. 堡垒机介绍
  4. 锂离子电池安全事故:安全性问题,还是可靠性
  5. NoSQL Redis
  6. 虚拟化 VMware ESXi(二)
  7. 虚拟化 KVM
  8. msqly
  9. 虚拟化 VMware ESXi(一)
  10. NoSQL MongoDB