这段时间项目中有个功能是像有道词典相机取词那样的一个工作,研究了好久,看不不少大神的代码,终于有了解决方案,思路是定义一个 Handler 来处理聚焦,每10毫秒聚焦一次,连续成功聚焦5次就执行拍照功能。我看到其他大神写的手机移动后就聚焦,功能很强大!我写的还有点缺陷,希望看到的大神能给完善下!谢谢!
我先定义了个SurfaceView:
package com.example.androidcamera;
import java.io.IOException;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* 相机基本预览类
* @author wanglei
*
*/
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
private static final String TAG = "CameraView";
private SurfaceHolder mySurfaceHolder;
private Camera myCamera;
// private PreviewCallback myPreviewCallback;//预览回调事件
// private PictureCallback myPictureCallback;//拍照回调事件
private AutoFocusCallback myAutoFocusCallback;
/** 创建构造器 */
@SuppressWarnings("deprecation")
public CameraView(Context context,Camera camera,AutoFocusCallback autoFocusCallback) {
super(context);
myCamera =camera;
// myPreviewCallback = previewCallback;
// myPictureCallback = pictureCallback;
myAutoFocusCallback = autoFocusCallback;
mySurfaceHolder = getHolder();
mySurfaceHolder.addCallback(this);
mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
/**
* 设置相机预览类
*/
public void surfaceCreated(SurfaceHolder holder) {
try {
Camera.Parameters parameters = myCamera.getParameters();
// Log.i(TAG, "摄像头的各项参数:"+parameters.flatten());
parameters.setPreviewSize(640, 480);//摄像头的像素
parameters.setPictureSize(640, 480);//拍摄出照片的大小
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setJpegQuality(100);//jpg图片的质量
parameters.setRotation(90);//相机旋转90度
myCamera.setParameters(parameters);//把参数设回给摄像头
myCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.d(TAG, "相机预览类设置错误:"+e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(mySurfaceHolder.getSurface() == null) return;
try {
myCamera.startPreview();
myCamera.setDisplayOrientation(90);
myCamera.setPreviewDisplay(mySurfaceHolder);
// myCamera.setPreviewCallback(myPreviewCallback);
myCamera.startPreview();
myCamera.autoFocus(myAutoFocusCallback);
// myCamera.takePicture(null, null, myPictureCallback);
} catch (Exception e) {
Log.d(TAG, "相机开始预览错误"+e.getMessage());
}
}
}
接下来是相机类:定义了连续聚焦
package com.example.androidcamera;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class CameraActivity extends Activity{
private static final String TAG = "CameraActivity";
private Camera myCamera;
private CameraView myCameraView;
private Handler autoFocusHandler;
private boolean previewing = true;
private int takePictureType=0;
private RelativeLayout layout;
private ImageView imageView;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera); //设置View
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置屏幕方向
autoFocusHandler = new Handler();
myCamera = Camera.open();//打开相机
myCameraView = new CameraView(this, myCamera,autoFocusCallback);
FrameLayout frameLayout = (FrameLayout)this.findViewById(R.id.cameraPreview);
frameLayout.addView(myCameraView);
textView = (TextView)this.findViewById(R.id.textmsg);
layout = (RelativeLayout)this.findViewById(R.id.returnMsg);
imageView = (ImageView)this.findViewById(R.id.imageview);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
layout.setVisibility(ViewGroup.GONE);
myCamera.startPreview();//开始预览
previewing = true;
myCamera.autoFocus(autoFocusCallback);
}
});
}
/** 关闭释放相机 */
protected void onPause() {
super.onPause();
if(myCamera!=null){
previewing = false;
myCamera.setPreviewCallback(null);
myCamera.release();
myCamera = null;
}
};
/** 拍照事件内部类 */
PictureCallback pictureCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.i(TAG, "执行:拍照事件内部类 ");
layout.setVisibility(ViewGroup.VISIBLE);
imageView.setImageBitmap(getBitmap(data));
try {//保存裁剪好的图片
File file = new File("mnt/sdcard/test.jpg");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
getBitmap(data).compress(Bitmap.CompressFormat.JPEG, 80, bos);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
/** 获取矩形区域内的截图 */
private Bitmap getBitmap(byte[] data) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//获取图像
// View myView = (View) this.findViewById(R.id.myView);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix m = new Matrix();
m.setRotate(90,(float) width/2, (float) height/ 2);
Bitmap testBitmap = Bitmap.createBitmap(bitmap, 0,0,width,height,m,true);//旋转图片
Bitmap finalBitmap = Bitmap.createBitmap(testBitmap, testBitmap.getWidth()/20, testBitmap.getHeight()/20, testBitmap.getWidth()/20*19, testBitmap.getHeight()/20*2);//截取图片
return finalBitmap;
}
/** 聚焦事件内部类 */
AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {//这里是连续聚焦算法
if (success && takePictureType < 6) {
takePictureType +=1;
} else if (takePictureType > 5) {
myCamera.takePicture(null, null, pictureCallback);
previewing = false;
takePictureType = 0;
} else {
takePictureType = 0;
}
autoFocusHandler.postDelayed(doAutoFocus, 10);// 每10毫秒连续聚焦
Log.i(TAG, "success:" + success + " | takePictureType:"+ takePictureType);
}
};
/** 聚焦线程 */
private Runnable doAutoFocus = new Runnable() {
@Override
public void run() {
if(previewing){
myCamera.autoFocus(autoFocusCallback);
}
}
};
}
自定义view用于遮罩:
package com.example.androidcamera;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
setLongClickable(true);
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//屏幕触摸事件待完成
return false;
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*这里就是绘制矩形区域*/
int width = this.getWidth();
int height = this.getHeight();
Paint paint = new Paint();
paint.setColor(0xaa000000);
canvas.drawRect(0, 0, width, height/20, paint);//top
canvas.drawRect(0, height/20, width/20, height/20*3, paint);//left
canvas.drawRect(width/20*19, height/20, width , height/20*3, paint);//right
canvas.drawRect(0, height/20*3, width, height, paint);//bottom
}
}
xml布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/cameraPreview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.androidcamera.MyView
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/returnMsg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" >
<ImageView
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp" />
<TextView
android:id="@+id/textmsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="150dp" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
系统清单文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidcamera"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<!-- 访问照相机的权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- sd卡读写数据目录的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 自动对焦的权限 -->
<uses-feature android:name="android.hardware.camera.autofocus" />
<!-- 访问网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- android:screenOrientation:固定屏幕显示方向 -->
<activity
android:name=".CameraActivity"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar" >
</activity>
</application>
</manifest>
代码就是这些了!希望有大神来帮忙完善下!谢谢。