@flyouting
        
        2014-03-19T03:08:14.000000Z
        字数 4535
        阅读 5499
    这是基于Android Studio及Fragment的相机开发的第一章,如果你还没准备好,先去github上拉一下我的一个示例工程。本章主要包含“SimpleCameraIntentFragment.”
在我们开始之前,我想花点时间讨论设备性能和重要的检查,这些都是我们应该发布一个使用相机的应用之前考虑的。
记住,市场上有很多Android设备能够运行你的应用,因此重要的是要做一些检查,以确保设备能够执行您想要执行的操作。
<uses-feature android:name="android.hardware.camera" android:required="true"/>
Context context = getActivity();PackageManager packageManager = context.getPackageManager();if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) == false){Toast.makeText(getActivity(), "This device does not have a camera.", Toast.LENGTH_SHORT) .show();return;}
在一些Android设备您可能还需要考虑下前后摄像头。您可以使用包管理器检查相机功能,代码如下:
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)
常用的检查:
打开实例程序,我们会看到 

当你选择 “take photo”按钮,一个外部相机程序会被调起,结果会显示在主窗口,在一个小窗口会显示缩略图。 
打开SimpleCameraIntentFragment.java 你会发现如下方法:
/*** Start the camera by dispatching a camera intent.*/protected void dispatchTakePictureIntent() {// Check if there is a camera.Context context = getActivity();PackageManager packageManager = context.getPackageManager();if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) == false) {Toast.makeText(getActivity(), "This device does not have a camera.", Toast.LENGTH_SHORT).show();return;}// Camera exists? Then proceed...Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// Ensure that there's a camera activity to handle the intentCameraActivity activity = (CameraActivity) getActivity();if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {// Create the File where the photo should go.// If you don't do this, you may get a crash in some devices.File photoFile = null;try {photoFile = createImageFile();} catch (IOException ex) {// Error occurred while creating the FileToast toast = Toast.makeText(activity, "There was a problem saving the photo...",Toast.LENGTH_SHORT);toast.show();}// Continue only if the File was successfully createdif (photoFile != null) {Uri fileUri = Uri.fromFile(photoFile);activity.setCapturedImageURI(fileUri);activity.setCurrentPhotoPath(fileUri.getPath());takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, activity.getCapturedImageURI());startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);}}}
我没有执行一个全面的相机硬件检查,只是执行了一个后置摄像头检查,如果设备之存在一个前置摄像头,那这个检查就会失败,
接下来就是接收和保存图片了,基本代码都是这样子:
/*** The activity returns with the photo.** @param requestCode* @param resultCode* @param data*/@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data){if (requestCode == REQUEST_TAKE_PHOTO && resultCode == Activity.RESULT_OK) {addPhotoToGallery();CameraActivity activity = (CameraActivity) getActivity();// Show the full sized image.setFullImageFromFilePath(activity.getCurrentPhotoPath(), mImageView);setFullImageFromFilePath(activity.getCurrentPhotoPath(), mThumbnailImageView);} else {Toast.makeText(getActivity(), "Image Capture Failed", Toast.LENGTH_SHORT).show();}}
注意看如下代码:
Uri fileUri = Uri.fromFile(photoFile);activity.setCapturedImageURI(fileUri);activity.setCurrentPhotoPath(fileUri.getPath());
记住,由于我们在一个Fragment里使用了相机,有一些额外的步骤可以跳过,以保证所有功能都正常。
在某些Android设备(例如,一些三星设备),您可能需要将从Intent传回的相机图像保存到一个文件中。当应用程序返回到前台时,该文件将不再是可用的,并由此可能会导致崩溃且没有异常抛出。
为了防止这种事故,我已经创建了一个特别的Activity:“CameraActivity”自动保存和恢复你所需要保存和读取的相机文件和Uri数据,过程安全。
接下里看一看CameraActivity,我就不罗列所有的代码了,但是在这个Activity里你可以看到保存了相机文件和Uri数据,并在onResume里恢复数据。
// Storage for camera image URI componentsprivate final static String CAPTURED_PHOTO_PATH_KEY = "mCurrentPhotoPath";private final static String CAPTURED_PHOTO_URI_KEY = "mCapturedImageURI";// Required for camera operations in order to save the image file on resume.private String mCurrentPhotoPath = null;private Uri mCapturedImageURI = null;@Overridepublic void onSaveInstanceState(Bundle savedInstanceState) {if (mCurrentPhotoPath != null) {savedInstanceState.putString(CAPTURED_PHOTO_PATH_KEY, mCurrentPhotoPath);}if (mCapturedImageURI != null) {savedInstanceState.putString(CAPTURED_PHOTO_URI_KEY, mCapturedImageURI.toString());}super.onSaveInstanceState(savedInstanceState);}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {if (savedInstanceState.containsKey(CAPTURED_PHOTO_PATH_KEY)) {mCurrentPhotoPath = savedInstanceState.getString(CAPTURED_PHOTO_PATH_KEY);}if (savedInstanceState.containsKey(CAPTURED_PHOTO_URI_KEY)) {mCapturedImageURI = Uri.parse(savedInstanceState.getString(CAPTURED_PHOTO_URI_KEY));}super.onRestoreInstanceState(savedInstanceState);}
实际上我在这里做的是存储然后回调必要的路径信息,然后Android设备就得到了文件的引用并通过一个Intent去保存,没有这些代码,相机应用会在onResume时崩溃。
这就是我所要说的安全的在Fragment里使用相机Intent。大家可以自由发挥写出自己的调用相机的代码。
翻译:@flyouting 
时间:2014/03/19 
源地址