Android开发官方文档---Capturing Photos
2015-12-24 17:14
495 查看
如果应用要使用Camera,添加<uses-feature>标签
<manifest ...>
<uses-featureandroid:name="android.hardware.camera"
android:required="true" />
...
</manifest>
如果Camera是应用使用到的功能但不是必要的就可以设置required属性为false
在应用里面可以调用hasSystemFeature(PackageManager.FEATURE_CAMERA) 决定是否使用Camera功能。
Android调用其他应用的功能需要三步:
(1)使用 Intent 描述想要的操作
static final intREQUEST_IMAGE_CAPTURE = 1;
private voiddispatchTakePictureIntent() {
Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
(2)调用Activity
调用startActivityForResult()之前为了安全先调用resolveActivity() 获取是否有Activity可以处理Intent的操作
(3)处理返回的数据
调用系统的Camera 会返回一个Intent,里面的data键值为一张小bitmap.这小Bitmap只是原图的压缩版.
重写 onActivityResult 方法获取返回的数据
@Override
protected voidonActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode ==REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundleextras = data.getExtras();
BitmapimageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
获取原图:
需要提供一个让Camera保存原图的文件,可以把图片添加到公共的存储区或自己应用的私有区域
getExternalStoragePublicDirectory() 获取外存储公共区域路径
getExternalFilesDir() 获取私有外存储区域路径
步骤:
(1)设置读写外存储权限,4.3版本以下需要添加WRITE_EXTERNAL_STORAGE权限,4.4之后不需要,因为外存储区域的文件都是应用私有的.添加maxSdkVersion属性表明4.3 以下版本需要该权限.
<manifest...>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>
...
</manifest>
(2)创建文件
StringmCurrentPhotoPath;
private FilecreateImageFile() throws IOException {
// Create an image file name
String timeStamp = newSimpleDateFormat("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 withACTION_VIEW intents
mCurrentPhotoPath = "file:" +image.getAbsolutePath();
return image;
}
(3) 现在 Intent 这样写
private voiddispatchTakePictureIntent() {
Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a cameraactivity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager())!= null) {
//Create the File where the photo should go
FilephotoFile = null;
try{
photoFile = createImageFile();
}catch (IOException ex) {
// Error occurred while creating the File
...
}
//Continue only if the File was successfully created
if(photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent,REQUEST_TAKE_PHOTO);
}
}
}
让其它应用扫描到自己私有的图片
因为保存在 getExternalFilesDir() 路径的图片不能被其他图片浏览软件访问,下面是简单的解决方案:
这种方式添加私有的图片到图片浏览器的数据库,让图片浏览器都能扫描到自己的私有图片.
private voidgalleryAddPic() {
IntentmediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f= new File(mCurrentPhotoPath);
UricontentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
//如果显示过多的图片内存不够用的话,可以对图片进行缩小来适应显示的区域,从而减少使用原图造成的内存不够情况。
private void setPic(){
// Get the dimensions of theView
int targetW =mImageView.getWidth();
int targetH =mImageView.getHeight();
// Get the dimensions of thebitmap
BitmapFactory.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 downthe image
int scaleFactor =Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into aBitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap =BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
调用系统Camera录制图像
第一步:获取Camera权限
<manifest ...>
<uses-featureandroid:name="android.hardware.camera"
android:required="true" />
...
</manifest>
如果设备没有Camera,为了可以在Google 应用商店也可以下载,可以设置 required 属性为false,在没有Camera的设备使用程序的时候要判断hasSystemFeature(PackageManager.FEATURE_CAMERA)是否Camera存在进行功能开启和关闭。
第二步:设置Intent
static final intREQUEST_VIDEO_CAPTURE = 1;
private voiddispatchTakeVideoIntent() {
Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if(takeVideoIntent.resolveActivity(getPackageManager()) != null) { //先判断是否有应用处理该Intent请求
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
}
}
第三步:处理返回结果
返回的是Video的存储位置Uri
@Override
protected voidonActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode ==REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
UrivideoUri = intent.getData();
mVideoView.setVideoURI(videoUri); //使用VideoView播放Video
}
}
控制Camera 对象
(1)使用open()获取Camera对象
private booleansafeCameraOpen(int id) {
boolean qOpened = false;
try {
releaseCameraAndPreview();
mCamera = Camera.open(id);
qOpened = (mCamera != null);
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
return qOpened;
}
private voidreleaseCameraAndPreview() {
mPreview.setCamera(null);
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
(2)实现接口处理数据
创建一个类实现 SurfaceHolder.Callback 接口,用来处理Camera硬件的数据,显示可以使用SurfaceView。
class Preview extendsViewGroup implements SurfaceHolder.Callback {
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
//Install a SurfaceHolder.Callback so we get notified when the
//underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
...
}
(3)设置和开启预览
public voidsetCamera(Camera camera) {
if (mCamera == camera) { return;}
stopPreviewAndFreeCamera();
mCamera =camera;
if (mCamera != null) {
List<Size> localSizes =mCamera.getParameters().getSupportedPreviewSizes();
mSupportedPreviewSizes = localSizes;
requestLayout();
try{
mCamera.setPreviewDisplay(mHolder);
}catch (IOException e) {
e.printStackTrace();
}
//Important: Call startPreview() to start updating the preview
//surface. Preview must be started before you can take a picture.
mCamera.startPreview();
}
}
设置 Camera 参数
public voidsurfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, setup the camera parameters and begin
// the preview.
Camera.Parameters parameters =mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
// Important: Call startPreview() tostart updating the preview surface.
// Preview must be started beforeyou can take a picture.
mCamera.startPreview();
}
设置预览的屏幕方向 setCameraDisplayOrientation()
API 14 之前必须先停止预览,再旋转屏幕方向,最后重启预览
开启预览可以使用 Camera.takePicture()拍照,传入Camera.PictureCallback 和Camera.ShutterCallback 反馈操作结果。
拍完照之后要恢复预览,便于用户拍下一张照片
@Override
public voidonClick(View v) {
switch(mPreviewState) {
case K_STATE_FROZEN:
mCamera.startPreview();
mPreviewState = K_STATE_PREVIEW;
break;
default:
mCamera.takePicture( null, rawCallback, null);
mPreviewState = K_STATE_BUSY;
} // switch
shutterBtnConfig();
}
使用完记得销毁Camera 对象
public voidsurfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when wereturn, so stop the preview.
if (mCamera != null) {
//Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
}
}
/**
* When this function returns, mCamera will be null.
*/
private voidstopPreviewAndFreeCamera() {
if (mCamera != null) {
//Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
//Important: Call release() to release the camera for use by other
//applications. Applications should release the camera immediately
//during onPause() and re-open() it during onResume()).
mCamera.release();
mCamera = null;
}
}
<manifest ...>
<uses-featureandroid:name="android.hardware.camera"
android:required="true" />
...
</manifest>
如果Camera是应用使用到的功能但不是必要的就可以设置required属性为false
在应用里面可以调用hasSystemFeature(PackageManager.FEATURE_CAMERA) 决定是否使用Camera功能。
Android调用其他应用的功能需要三步:
(1)使用 Intent 描述想要的操作
static final intREQUEST_IMAGE_CAPTURE = 1;
private voiddispatchTakePictureIntent() {
Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
(2)调用Activity
调用startActivityForResult()之前为了安全先调用resolveActivity() 获取是否有Activity可以处理Intent的操作
(3)处理返回的数据
调用系统的Camera 会返回一个Intent,里面的data键值为一张小bitmap.这小Bitmap只是原图的压缩版.
重写 onActivityResult 方法获取返回的数据
@Override
protected voidonActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode ==REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundleextras = data.getExtras();
BitmapimageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
获取原图:
需要提供一个让Camera保存原图的文件,可以把图片添加到公共的存储区或自己应用的私有区域
getExternalStoragePublicDirectory() 获取外存储公共区域路径
getExternalFilesDir() 获取私有外存储区域路径
步骤:
(1)设置读写外存储权限,4.3版本以下需要添加WRITE_EXTERNAL_STORAGE权限,4.4之后不需要,因为外存储区域的文件都是应用私有的.添加maxSdkVersion属性表明4.3 以下版本需要该权限.
<manifest...>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>
...
</manifest>
(2)创建文件
StringmCurrentPhotoPath;
private FilecreateImageFile() throws IOException {
// Create an image file name
String timeStamp = newSimpleDateFormat("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 withACTION_VIEW intents
mCurrentPhotoPath = "file:" +image.getAbsolutePath();
return image;
}
(3) 现在 Intent 这样写
private voiddispatchTakePictureIntent() {
Intent takePictureIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a cameraactivity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager())!= null) {
//Create the File where the photo should go
FilephotoFile = null;
try{
photoFile = createImageFile();
}catch (IOException ex) {
// Error occurred while creating the File
...
}
//Continue only if the File was successfully created
if(photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent,REQUEST_TAKE_PHOTO);
}
}
}
让其它应用扫描到自己私有的图片
因为保存在 getExternalFilesDir() 路径的图片不能被其他图片浏览软件访问,下面是简单的解决方案:
这种方式添加私有的图片到图片浏览器的数据库,让图片浏览器都能扫描到自己的私有图片.
private voidgalleryAddPic() {
IntentmediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f= new File(mCurrentPhotoPath);
UricontentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
//如果显示过多的图片内存不够用的话,可以对图片进行缩小来适应显示的区域,从而减少使用原图造成的内存不够情况。
private void setPic(){
// Get the dimensions of theView
int targetW =mImageView.getWidth();
int targetH =mImageView.getHeight();
// Get the dimensions of thebitmap
BitmapFactory.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 downthe image
int scaleFactor =Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into aBitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap =BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
调用系统Camera录制图像
第一步:获取Camera权限
<manifest ...>
<uses-featureandroid:name="android.hardware.camera"
android:required="true" />
...
</manifest>
如果设备没有Camera,为了可以在Google 应用商店也可以下载,可以设置 required 属性为false,在没有Camera的设备使用程序的时候要判断hasSystemFeature(PackageManager.FEATURE_CAMERA)是否Camera存在进行功能开启和关闭。
第二步:设置Intent
static final intREQUEST_VIDEO_CAPTURE = 1;
private voiddispatchTakeVideoIntent() {
Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if(takeVideoIntent.resolveActivity(getPackageManager()) != null) { //先判断是否有应用处理该Intent请求
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
}
}
第三步:处理返回结果
返回的是Video的存储位置Uri
@Override
protected voidonActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode ==REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
UrivideoUri = intent.getData();
mVideoView.setVideoURI(videoUri); //使用VideoView播放Video
}
}
控制Camera 对象
(1)使用open()获取Camera对象
private booleansafeCameraOpen(int id) {
boolean qOpened = false;
try {
releaseCameraAndPreview();
mCamera = Camera.open(id);
qOpened = (mCamera != null);
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
return qOpened;
}
private voidreleaseCameraAndPreview() {
mPreview.setCamera(null);
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
(2)实现接口处理数据
创建一个类实现 SurfaceHolder.Callback 接口,用来处理Camera硬件的数据,显示可以使用SurfaceView。
class Preview extendsViewGroup implements SurfaceHolder.Callback {
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
//Install a SurfaceHolder.Callback so we get notified when the
//underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
...
}
(3)设置和开启预览
public voidsetCamera(Camera camera) {
if (mCamera == camera) { return;}
stopPreviewAndFreeCamera();
mCamera =camera;
if (mCamera != null) {
List<Size> localSizes =mCamera.getParameters().getSupportedPreviewSizes();
mSupportedPreviewSizes = localSizes;
requestLayout();
try{
mCamera.setPreviewDisplay(mHolder);
}catch (IOException e) {
e.printStackTrace();
}
//Important: Call startPreview() to start updating the preview
//surface. Preview must be started before you can take a picture.
mCamera.startPreview();
}
}
设置 Camera 参数
public voidsurfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, setup the camera parameters and begin
// the preview.
Camera.Parameters parameters =mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
// Important: Call startPreview() tostart updating the preview surface.
// Preview must be started beforeyou can take a picture.
mCamera.startPreview();
}
设置预览的屏幕方向 setCameraDisplayOrientation()
API 14 之前必须先停止预览,再旋转屏幕方向,最后重启预览
开启预览可以使用 Camera.takePicture()拍照,传入Camera.PictureCallback 和Camera.ShutterCallback 反馈操作结果。
拍完照之后要恢复预览,便于用户拍下一张照片
@Override
public voidonClick(View v) {
switch(mPreviewState) {
case K_STATE_FROZEN:
mCamera.startPreview();
mPreviewState = K_STATE_PREVIEW;
break;
default:
mCamera.takePicture( null, rawCallback, null);
mPreviewState = K_STATE_BUSY;
} // switch
shutterBtnConfig();
}
使用完记得销毁Camera 对象
public voidsurfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when wereturn, so stop the preview.
if (mCamera != null) {
//Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
}
}
/**
* When this function returns, mCamera will be null.
*/
private voidstopPreviewAndFreeCamera() {
if (mCamera != null) {
//Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
//Important: Call release() to release the camera for use by other
//applications. Applications should release the camera immediately
//during onPause() and re-open() it during onResume()).
mCamera.release();
mCamera = null;
}
}
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories