Camera
在app中使用相机的两种方式:
1.调用系统相机
隐式启动
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
2.自定义相机
注册:
<intent-filter >
<action android:name="android.media.action.IMAGE_CAPTURE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
3.获取拍照图片
private void startCamera1(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
}
private void startCamera2(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定想要的文件输出路径,就不用去data里拿了
filePath = Environment.getExternalStorageState() + "/temp.png";
**Uri photoUri = Uri.fromFile(new File(filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);**
startActivityForResult(intent, 2);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (resultCode == 1) {
**// 这样子拿的是缩略图,不用担心内存溢出
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);**
} else if (resultCode == 2) {
// 直接拿原图
FileInputStream fis = null;
**fis = new FileInputStream(filePath);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);//为什么不用担心内存溢出?!**
fis.close();
4.自定义相机代码示例
总结一下:1.用open方法在onresume里创建camera实例,在onpause里释放camera
2.实现surfaceholder的addcallback接口,把camera与surfaceview绑定
3.实现camera.takepicture()相机回调方法
//相机捕获图像是调用,此时图像数据处理还未完成
private Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback(){
@Override
public void onShutter() {
// TODO Auto-generated method stub
}};
//在原始图像数据可用时调用(拍好了,数据放在data中)
private Camera.PictureCallback mJpegCallBack = new Camera.PictureCallback(){
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File file = new File("/sdcard/temp.jpg");
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);//把照片放到指定位置
fos.close();
Intent intent = new Intent(CustomCameraActivity.this , ResultActivity.class);
intent.putExtra("PicPath", file.getAbsolutePath());
startActivity(intent);
CustomCameraActivity.this.finish();//拍完跳到另一个activity,并结束当前activity
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
takeButton = (Button) findViewById(R.id.take);
takeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//要实现三个接口传入
camera.takePicture(null, null, mJpegCallBack);
}
});
surfaceView = (SurfaceView) findViewById(R.id.preview);
surfaceView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
camera.autoFocus(null);//点击屏幕自动对焦(如何不用点就自动对焦?)
}
});
SurfaceHolder holder = surfaceView.getHolder();
holder.addCallback(new Callback() {
@Override
//surface与其客户端进行关联
public void surfaceCreated(SurfaceHolder holder) {
try {
if(camera != null){
camera.setPreviewDisplay(holder);//将camera与holder绑定
camera.setDisplayOrientation(90);//默认横屏,设置旋转角度
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
//surface首次显示在屏幕上时调用。通过参数可以设置相关属性;通知客户端预览区域大小
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
Parameters parameters = camera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);//设置格式
parameters.setFocusMode(Camera.Parameters.FLASH_MODE_AUTO);//设置对焦模式(自动对焦)
//parameters.setPreviewSize(800, 600);//设置预览大小
List<Size> previewSizes = parameters.getSupportedPreviewSizes();//返回的数组中每个实例封装了一个具体的图片宽高
Size s1 = getBestSize(previewSizes, width, height);//拿到最佳尺寸
parameters.setPreviewSize(s1.width, s1.height);//设置预览大小
List<Size> pictureSizes = parameters.getSupportedPictureSizes();
Size s2 = getBestSize(pictureSizes, width, height);
parameters.setPictureSize(s1.width, s1.height);//设置最后图片创建大小
camera.setParameters(parameters);
try{
camera.startPreview();//开始预览
}catch(Exception e){
camera.release();//万一启动失败,释放资源
}
}
@Override
//surface从屏幕上移除时调用,被销毁,通知客户端停止使用surfa
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera != null){
camera.stopPreview();
}
}
});
}
@Override
protected void onResume() {
super.onResume();
// 初始化camera
if (camera == null) {
camera = Camera.open();
}
}
@Override
protected void onPause() {
super.onPause();
// 释放camera
if (camera != null) {
camera.release();
}
}
//接受一组预览尺寸,找出最大像素数目的尺寸
private Size getBestSize(List<Size> sizes ,int width , int height){
Size bestSize = sizes.get(0);
int largestArea = bestSize.width * bestSize.height;
for(Size s : sizes){
int area = s.width * s.height;
if(area > largestArea){
bestSize = s;
largestArea = area;
}
}
return bestSize;
}
检查设备是否带有相机
PackageManager pm = getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) &&
!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
mPhotoButton.setEnabled(false);
}
隐藏状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
使之能截获点击,不应响应 android:clickable="true"
水印:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView //也可加其他view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="水印"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
相机拍摄的照片太大,需缩放
//拿屏幕宽高
Display display = getWindowManager().getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
//拿图片宽高
Options options = new Options();
options.inJustDecodeBounds = true;//不为图片申请内存,只获取宽高
BitmapFactory.decodeFile(pathName , options);
int srcWidth = options.outWidth;
int srcHeight = options.outHeight;
//计算缩放比例
int scale = 1;
if(srcWidth > screenWidth || srcWidth > screenHeight){
if(srcWidth > srcHeight){
scale = Math.round(srcHeight / screenHeight);
}else{
scale = Math.round(srcWidth / screenWidth);
}
}
//缩放
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile( pathName ,options);