[关闭]
@flyouting 2014-03-19T11:08:14.000000Z 字数 4535 阅读 5137

Android相机开发指南(一)

这是基于Android Studio及Fragment的相机开发的第一章,如果你还没准备好,先去github上拉一下我的一个示例工程。本章主要包含“SimpleCameraIntentFragment.”

在我们开始之前,我想花点时间讨论设备性能和重要的检查,这些都是我们应该发布一个使用相机的应用之前考虑的。

记住,市场上有很多Android设备能够运行你的应用,因此重要的是要做一些检查,以确保设备能够执行您想要执行的操作。

  1. <uses-feature android:name="android.hardware.camera" android:required="true"/>
  1. Context context = getActivity();
  2. PackageManager packageManager = context.getPackageManager();
  3. if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) == false){
  4. Toast.makeText(getActivity(), "This device does not have a camera.", Toast.LENGTH_SHORT) .show();
  5. return;
  6. }

有一个摄像头?有多个摄像头?

在一些Android设备您可能还需要考虑下前后摄像头。您可以使用包管理器检查相机功能,代码如下:

  1. context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)

常用的检查:

Fragments and Camera Intents

打开实例程序,我们会看到
此处输入图片的描述

当你选择 “take photo”按钮,一个外部相机程序会被调起,结果会显示在主窗口,在一个小窗口会显示缩略图。
打开SimpleCameraIntentFragment.java 你会发现如下方法:

  1. /**
  2. * Start the camera by dispatching a camera intent.
  3. */
  4. protected void dispatchTakePictureIntent() {
  5. // Check if there is a camera.
  6. Context context = getActivity();
  7. PackageManager packageManager = context.getPackageManager();
  8. if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) == false) {
  9. Toast.makeText(getActivity(), "This device does not have a camera.", Toast.LENGTH_SHORT)
  10. .show();
  11. return;
  12. }
  13. // Camera exists? Then proceed...
  14. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  15. // Ensure that there's a camera activity to handle the intent
  16. CameraActivity activity = (CameraActivity) getActivity();
  17. if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
  18. // Create the File where the photo should go.
  19. // If you don't do this, you may get a crash in some devices.
  20. File photoFile = null;
  21. try {
  22. photoFile = createImageFile();
  23. } catch (IOException ex) {
  24. // Error occurred while creating the File
  25. Toast toast = Toast.makeText(activity, "There was a problem saving the photo...",
  26. Toast.LENGTH_SHORT);
  27. toast.show();
  28. }
  29. // Continue only if the File was successfully created
  30. if (photoFile != null) {
  31. Uri fileUri = Uri.fromFile(photoFile);
  32. activity.setCapturedImageURI(fileUri);
  33. activity.setCurrentPhotoPath(fileUri.getPath());
  34. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, activity.getCapturedImageURI());
  35. startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
  36. }
  37. }
  38. }

我没有执行一个全面的相机硬件检查,只是执行了一个后置摄像头检查,如果设备之存在一个前置摄像头,那这个检查就会失败,

接下来就是接收和保存图片了,基本代码都是这样子:

  1. /**
  2. * The activity returns with the photo.
  3. *
  4. * @param requestCode
  5. * @param resultCode
  6. * @param data
  7. */
  8. @Override
  9. public void onActivityResult(int requestCode, int resultCode, Intent data)
  10. {
  11. if (requestCode == REQUEST_TAKE_PHOTO && resultCode == Activity.RESULT_OK) {
  12. addPhotoToGallery();
  13. CameraActivity activity = (CameraActivity) getActivity();
  14. // Show the full sized image.
  15. setFullImageFromFilePath(activity.getCurrentPhotoPath(), mImageView);
  16. setFullImageFromFilePath(activity.getCurrentPhotoPath(), mThumbnailImageView);
  17. } else {
  18. Toast.makeText(getActivity(), "Image Capture Failed", Toast.LENGTH_SHORT).show();
  19. }
  20. }

*在Fragments中捕获Activity Results *

注意看如下代码:

  1. Uri fileUri = Uri.fromFile(photoFile);
  2. activity.setCapturedImageURI(fileUri);
  3. activity.setCurrentPhotoPath(fileUri.getPath());

记住,由于我们在一个Fragment里使用了相机,有一些额外的步骤可以跳过,以保证所有功能都正常。

在某些Android设备(例如,一些三星设备),您可能需要将从Intent传回的相机图像保存到一个文件中。当应用程序返回到前台时,该文件将不再是可用的,并由此可能会导致崩溃且没有异常抛出。

为了防止这种事故,我已经创建了一个特别的Activity:“CameraActivity”自动保存和恢复你所需要保存和读取的相机文件和Uri数据,过程安全。

无崩溃情况下获取图片

接下里看一看CameraActivity,我就不罗列所有的代码了,但是在这个Activity里你可以看到保存了相机文件和Uri数据,并在onResume里恢复数据。

  1. // Storage for camera image URI components
  2. private final static String CAPTURED_PHOTO_PATH_KEY = "mCurrentPhotoPath";
  3. private final static String CAPTURED_PHOTO_URI_KEY = "mCapturedImageURI";
  4. // Required for camera operations in order to save the image file on resume.
  5. private String mCurrentPhotoPath = null;
  6. private Uri mCapturedImageURI = null;
  7. @Override
  8. public void onSaveInstanceState(Bundle savedInstanceState) {
  9. if (mCurrentPhotoPath != null) {
  10. savedInstanceState.putString(CAPTURED_PHOTO_PATH_KEY, mCurrentPhotoPath);
  11. }
  12. if (mCapturedImageURI != null) {
  13. savedInstanceState.putString(CAPTURED_PHOTO_URI_KEY, mCapturedImageURI.toString());
  14. }
  15. super.onSaveInstanceState(savedInstanceState);
  16. }
  17. @Override
  18. protected void onRestoreInstanceState(Bundle savedInstanceState) {
  19. if (savedInstanceState.containsKey(CAPTURED_PHOTO_PATH_KEY)) {
  20. mCurrentPhotoPath = savedInstanceState.getString(CAPTURED_PHOTO_PATH_KEY);
  21. }
  22. if (savedInstanceState.containsKey(CAPTURED_PHOTO_URI_KEY)) {
  23. mCapturedImageURI = Uri.parse(savedInstanceState.getString(CAPTURED_PHOTO_URI_KEY));
  24. }
  25. super.onRestoreInstanceState(savedInstanceState);
  26. }

实际上我在这里做的是存储然后回调必要的路径信息,然后Android设备就得到了文件的引用并通过一个Intent去保存,没有这些代码,相机应用会在onResume时崩溃。

这就是我所要说的安全的在Fragment里使用相机Intent。大家可以自由发挥写出自己的调用相机的代码。

翻译:@flyouting
时间:2014/03/19
源地址

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注