网站建设用哪个,车陂手机网站开发,天津建设工程信息网登录不了,手机优化专家下载原文地址#xff1a;http://android.xsoftlab.net/training/camera/index.html
导言
在富媒体开始流行之前#xff0c;整个世界是一个灰暗且平淡无奇的地方。还记得Gopher吗#xff1f;我或许不记得了。自从APP成为用户生活的一部分之后#xff0c;这便给他们提供了一种方…原文地址http://android.xsoftlab.net/training/camera/index.html
导言
在富媒体开始流行之前整个世界是一个灰暗且平淡无奇的地方。还记得Gopher吗我或许不记得了。自从APP成为用户生活的一部分之后这便给他们提供了一种方式可以来存放他们生活的细节。使用设备上的相机程序可以使用户扩大周围的视野或者见解使以独特的化身记录各个角落里的奇闻异事或者只是简单的分享他们的境遇。
这节课会通过已有的相机应用以超级简单的方式快速过一下。在稍后的课程中会逐渐深入的学习如何直接控制相机硬件。
简单拍照
这节课会展示如何使用已有的相机应用来拍照。
假设你正在实现一个众包的天气服务程序这个服务可以使运行在设备上的客户端APP通过天空的混合照片生成全部的天气示意图(言下之意就是可以生成各种天气的天气图像)而整合照片只是程序很小的一部分功能。你并不想在这里花费很多时间也不想彻底的改造相机程序。幸运的是大多数的安卓设备至少已经安装了一款相机应用。这节课就是学习如何利用这个应用为程序拍一张照片。
请求相机权限
如果拍照是程序的一项必要需求那么需要在Google Play上限制它的分类为拥有相机类。为了告知系统程序是基于相机的需要在清单文件中添加 标签。
manifest ... uses-feature android:nameandroid.hardware.cameraandroid:requiredtrue /...
/manifest
如果程序需要使用但是为了整个功能而不强制要求相机那么可以设置android:required为false。这样做的话Google Play会允许不带相机的设备下载你的程序。不过你有责任需要在运行时通过调用hasSystemFeature(PackageManager.FEATURE_CAMERA)方法检查设备上的相机是否可用。如果相机是不可用的你应该禁用掉与相机相关的功能。
通过相机APP拍照
Android通过授权的方式让其他程序通过调用一个Intent来描述你想要做的事情。这个过程包含了三块Intent本身一个启动外部Activity的调用以及一些当焦点返回Activity时处理图像数据的代码。
下面代码的功能用于调用一个意图来拍摄照片
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()方法被一个调用resolveActivity()方法的条件所保护这个方法返回了可以处理这个Intent的第一个activity组件。执行这项检查是非常重要的因为如果你调用startActivityForResult()方法所使用的Intent没有APP可以处理的话那么你的APP将会崩溃。所以只要结果不是null那么就意味着可以安全使用这个Intent。
获取缩略图像
如果简单的拍照功能并不是APP的主要功能那么你可能想通过相机应用获得一张照片并且利用这张照片做点什么事情。
Android的相机应用会将照片作为一个小的Bitmap对象打包进Intent中然后通过onActivityResult()方法将该Intent返回。具体的Bitmap对象会附加在键”data”后。下面的代码段接收到这个图像并将它展示到了一个ImageView中:
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);}
} Note: 从”data”中获得的缩略图像可能适合用于图标上面但不适用于很大的图标。处理全尺寸的图像需要花费更多一点的工作。 保存全尺寸照片
如果你提供了文件的保存路径的话那么Android相机应用会将全尺寸的照片保存在这个地方。你必须提供文件的全路径这个路径所指向的地方就是相机应用将要保存照片的地方。
通常情况下用户通过相机应用所拍摄的任何照片都应该被保存在设备外部存储器上的一个公共文件夹中这样就可以使所有的APP都可以访问。这个适用于存放共享照片的目录由getExternalStoragePublicDirectory()提供并需要传递DIRECTORY_PICTURES参数。因为由这个方法所提供的分享目录适用于所有的APP读取以及写入分别需要READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。写入权限隐式地包含了读取权限所有如果你需要写入到外部存储上的话只需要请求一个权限就可以
manifest ...uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE /...
/manifest
然而如果你希望这些照片只是被保存在APP的私有目录中的话你可以使用getExternalFilesDir()方法提供的目录来做替换方案。在Android 4.3之前写入到这个目录需要WRITE_EXTERNAL_STORAGE权限。从Android 4.4开始这个权限不再被需要因为这个目录不再对其它APP可见所以这里声明的权限只对低版本的Android适用并需要添加maxSdkVersion属性
manifest ...uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGEandroid:maxSdkVersion18 /...
/manifest Note:当用户卸载了你的APP时那么通过getExternalFilesDir()方法所提供的目录下的文件也会一并删除。 一旦你决定了文件存储的目录需要创建一个防止冲突的文件名称。你可能还希望将路径保存到一个成员变量中以便稍后再使用。这里在方法中有一个示例的解决办法它会通过日期时间戳来对新照片返回一个唯一的文件名称
String mCurrentPhotoPath;
private File createImageFile() throws IOException {// Create an image file nameString 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 intentsmCurrentPhotoPath 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 theres a camera activity to handle the intentif (takePictureIntent.resolveActivity(getPackageManager()) ! null) {// Create the File where the photo should goFile photoFile null;try {photoFile createImageFile();} catch (IOException ex) {// Error occurred while creating the File...}// Continue only if the File was successfully createdif (photoFile ! null) {takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photoFile));startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);}}
}
添加照片到相册
当你通过一个意图创建了一张照片你应该知道图像位于何处因为在上面的代码中你告诉了照片保存的位置。对于其他人而言可能使照片最简单的访问方式就是使照片对系统的媒体扫描器(Media Provider)是可访问的。 Note: 如果照片保存的文件目录是由getExternalFilesDir()所提供的那么媒体扫描器是不能访问这些文件的因为照片对于你的APP来说是私有的。 下面的示例方法演示了如何调用系统的扫描器来添加你的照片到媒体扫描器(Media Provider)的数据库中使得这些照片可以被系统的相册应用或者其它APP可访问
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 Viewint targetW mImageView.getWidth();int targetH mImageView.getHeight();// Get the dimensions of the bitmapBitmapFactory.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 imageint scaleFactor Math.min(photoW/targetW, photoH/targetH);// Decode the image file into a Bitmap sized to fill the ViewbmOptions.inJustDecodeBounds false;bmOptions.inSampleSize scaleFactor;bmOptions.inPurgeable true;Bitmap bitmap BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);mImageView.setImageBitmap(bitmap);
}