Android Fragment中使用Intent组件拍照
要在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
业界
职场
创业
访谈
在国外
在安卓Fragment中使用Intent组件拍照
说明: 这篇文章主要介绍了如何在安卓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):
Android Fragment中使用Intent组件拍照的更多相关文章
- 【转】Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法
重构了下之前自己的一个新闻客户端,全部使用了Fragment来进行页面切换,只有一个入口Activity作为程序的启动Activity,其中有一个界面需要调用摄像头识别二维码, 于是就会用到Surfa ...
- Android开发中使用Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 首先,我们先看拨号界面,代码如下: Intent intent =new Intent(); intent. ...
- android Fragment中使用Toolbar
在Activity中可以直接使用 setSupportActionBar(toolbar); 就可以重写 onCreateOptionsMenu 和 onOptionsItemSelected 方法: ...
- Android系统中标准Intent的使用
Android系统用于Activity的标准Intent 1.根据联系人ID显示联系人信息= Intent intent=new Intent(); intent.setAction(Intent.A ...
- Android 开发中使用Intent传递数据的方法
Activity之间通过Intent传递值,支持基本数据类型和String对象及 它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.shor ...
- 调用Android系统设置中的Intent
开发Android软件时,常常需要打开系统设置或信息界面,来设置相关系统项或查看系统的相关信息,这时我们就可以使用以下语句来实现:(如打开“无线和网络设置”界面) Intent intent = ne ...
- Android Fragment中调用getActivity为null的问题
在使用fragment的时候经常会遇到getActivity()为null的情况.比如我在一个异步网路请求的回调中调用了getActivity()就会出现空指针问题.之前解决这个问题,通常都是直 ...
- Android --Fragment中异步HTTP请求
1.自定义异步Task /** * 异步获取实时数据 */ public class TimerDataTask extends AsyncTask<Void, Void, Boolean> ...
- 关于Android中的四大组件(Service的开启与关闭)
前言 服务(Service)是Android系统中的四大组件之中的一个.服务主要用于两个目的:后台执行和跨进程訪问. 通过启动 一个服务.能够在不显示界面的前提下在后台执行指定的任务,这样能够不影响用 ...
随机推荐
- java设计模式--结构型模式--享元模式
享元模式 概述 运用共享技术有效地支持大量细粒度的对象. 适用性 当都具备下列情况时,使用Flyweight模式: 1.一个应用程序使用了大量的对象. 2.完全由于使用大量的对象,造成很大的存储开销. ...
- Java内存回收(垃圾回收)机制总结
一.背景: Java程序员编写程序时,对于新建的对象,当不再需要此对象时,不必去释放这个对象所占用的空间,这个工作是由Java虚拟机自己完成的 ,即内存回收或垃圾回收. 二.如何知道一个对象所占用的空 ...
- 福建省队集训被虐记——DAY4
啊啊啊啊啊啊第四天考的是我最不擅长的图论--整个人都斯巴达了 //另外不得不吐槽下午的上课讲的都是网络流--难道是出题人觉得图论里除了网络流以外的其他算法都没有人权图样图森破? 愚蠢的算法(clums ...
- Apache本地服务无法自启动问题解决
问题描述: Windows不能在本地计算机启动Apache2.有关更多信息,查阅系统事件日志.如果这是非Microsoft服务,请与服务厂商联系,并参考特定服务错误代码1. 解决方案: 1.检查Apa ...
- hihoCoder 1098
题目大意:n 个城市由 m 条边连接,每条边有权值,求将所有城市连接起来时的最小权值和. 代码: #include<iostream> #include<cstdio> #in ...
- 精确覆盖DLX算法模板
代码 struct DLX { int n,id; int L[maxn],R[maxn],U[maxn],D[maxn]; ]; ) //传列长 { n=nn; ;i<=n;i++) U[i] ...
- Best Cow Line (POJ 3217)
给定长度为N的字符串S,要构造一个长度为N的字符串T,起初,T是一个空串,随后反复进行下列任意操作. *从S的头部删除一个字符,加到T的尾部 *从S的尾部删除一个字符,加到T的尾部 目标是要构造字典序 ...
- batch 批处理获取系统时间
文件test.bat,内容命令如下: @echo off set filename=%,%-%,%-%,% %,%:%,%:%,% echo %filename% pause
- 《Java程序员面试笔试宝典》之 instanceof有什么作用
instanceof是Java语言中的一个二元运算符,它的作用是判断一个引用类型的变量所指向的对象是否是一个类(或接口.抽象类.父类)的实例,即它左边的对象是否是它右边的类的实例,返回boolean类 ...
- Gradle Tips#1-tasks
原文链接 以这篇博客開始,我将写一系列关于Gradle的文章,用来记录接触Gradle构建脚本以来我所理解的Gradle. 今天要讲的就是Gradle tasks以及task的配置和运行.可能有的读者 ...