要在activity里面去接受,然后传递给fragment对象,fragment有很多回调调用不到
你的设备有摄像头吗?
为了确保市场上的大多数设备都能运行你的程序,必须在项目中做一些检测,保证使用的设备可以执行你的代码。
我们可以这么做:
- 在程序的配置清单文件中标明要求使用摄像头;
- 在代码中用
PackageManager
进行设备功能检测;
在项目的androidManifest文件中添加使用摄像头权限
android.hardware.camera
(在一个Fragment中)用PackageManager
在代码中检测设备是否含有摄像头,代码如下:
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; }
如果有一个或者多个摄像头怎么办?
在一些安卓设备上会有前置摄像头和后置摄像头,我们可以用PackageManager
来对摄像头进行功能检测,例如:
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)
通常我们需要检测的是摄像头的这些功能:
- FEATURE_CAMERA_FRONT (检测是否含有前置摄像头)
- FEATURE_CAMERA (检测是否含有后置摄像头)
- FEATURE_CAMERA_ANY (检测是否含有任意一个摄像头)
Fragment和摄像头Intent组件
用Android Studio打开我们的示例代码,然后在navigation drawer中选择“Simple Camera Intent”,你会看到如下画面:
当你选择”Take Photo“,外部的拍照程序就会弹出来,然后我们就可以拍照了。拍照的结果会被显示在主界面上,缩略图也会显示在一个小区域里。打开SimpleCameraIntentFragment.java,可以看到下面这个方法(摘录自Google’s Simple Camera documentation):
/** * 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 intent CameraActivity 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 File Toast toast = Toast.makeText(activity, "There was a problem saving the photo...", Toast.LENGTH_SHORT); toast.show(); } // Continue only if the File was successfully created if (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 */ * @Override public 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(); } }
在Fragment中获取Activity返回结果
接下来我们关注这几行代码:
Uri fileUri = Uri.fromFile(photoFile); activity.setCapturedImageURI(fileUri); activity.setCurrentPhotoPath(fileUri.getPath());
我们知道,当选择使用(由Activity管理的)Fragment时,为了保证所有部件运行正常,需要额外处理一些Fragment限制。在某些设备上(比如三星),你必须把返回结果的图像数据保存到一个文件中(该文件在使用Intent时需要提供)。但是当程序从照相程序中返回到前台时,这个文件就不可用了,然后程序会莫名崩溃了。
为了防止程序崩溃,我已经写了一个特别的Activity
——“CameraActivity”,可以自动保存和恢复摄像头的数据文件和Uri数据。当程序的生命周期改变时,我们需要这些数据。
安全地获取图片数据
我们来看看CameraActivity,这里就不全部贴出代码了,但是你可以看到这个Activity
会在resume
中保存和恢复摄像头的数据文件和Uri数据。
private 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; @Override public 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); } @Override protected 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); }
事实上我做的只是对这些需要的信息用Intent
进行保存和恢复。这样,程序就知道该从哪里找到需要引用的文件。加入没有这些代码,程序在onResume
中会崩溃。
以上这就是关于在Fragment中怎么用摄像头Intent组件进行拍照的简单教程,你可以随意使用以上所提供的源码进行修改使用。
- 导航条 -
首页
最新文章
经典回顾
开发
- Web前端
- Python
- Android
- iOS
- Java
- C/C++
- PHP
- .NET
- Ruby
- Go
设计
- UI设计
- 网页设计
- 交互设计
- 用户体验
- 设计教程
- 设计职场
极客
IT技术
- Linux
- UNIX
- MySQL
- NoSQL
- 数据库
- Git
- 机器学习
- 算法
- 测试
- 信息安全
- Vim
业界
职场
创业
访谈
在国外
伯乐在线 > 首页 > 所有文章 > Android > 在安卓Fragment中使用Intent组件拍照
在安卓Fragment中使用Intent组件拍照
2014/03/26 · Android, 开发 · 1 评论· 安卓开发, 摄像应用
分享到:0
本文由 伯乐在线 - chris 翻译。未经许可,禁止转载!
英文出处:airpair。欢迎加入翻译组。
说明: 这篇文章主要介绍了如何在安卓Fragment中使用摄像头拍照并保存图像和缩略图。
这篇文章是我的“Android Studio下用Fragment进行摄像头开发系列文章五篇”的第一篇,如果你还没做好准备,可以先看看我的代码,GitHub:UltimateAndroidCameraGuide。这篇教程中也会详细对代码进行说明,主要参考这个文件:SimpleCameraIntentFragment.java。
在开始之前,先花点时间说明一下手机设备的功能和发布App时需要考虑的设备功能检测问题。
你的设备有摄像头吗?
为了确保市场上的大多数设备都能运行你的程序,必须在项目中做一些检测,保证使用的设备可以执行你的代码。
我们可以这么做:
- 在程序的配置清单文件中标明要求使用摄像头;
- 在代码中用
PackageManager
进行设备功能检测;
在项目的androidManifest文件中要求使用摄像头,代码如下:
1 2 |
;html-script:false] <uses-feature android:name="android.hardware.camera"android:required="true"/> |
(在一个Fragment中)用PackageManager
在代码中检测设备是否含有摄像头,代码如下:
Java
1 2 3 4 5 6 7 8 9 |
;html-script:false] 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; } |
如果有一个或者多个摄像头怎么办?
在一些安卓设备上会有前置摄像头和后置摄像头,我们可以用PackageManager
来对摄像头进行功能检测,例如:
Java
1 2 |
;html-script:false] context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA) |
通常我们需要检测的是摄像头的这些功能:
- FEATURE_CAMERA_FRONT (检测是否含有前置摄像头)
- FEATURE_CAMERA (检测是否含有后置摄像头)
- FEATURE_CAMERA_ANY (检测是否含有任意一个摄像头)
Fragment和摄像头Intent组件
用Android Studio打开我们的示例代码,然后在navigation drawer中选择“Simple Camera Intent”,你会看到如下画面:
当你选择”Take Photo“,外部的拍照程序就会弹出来,然后我们就可以拍照了。拍照的结果会被显示在主界面上,缩略图也会显示在一个小区域里。打开SimpleCameraIntentFragment.java,可以看到下面这个方法(摘录自Google’s Simple Camera documentation):