在我們app中經常會調用相機進行拍照,然後把拍下來的圖片保存在本地,再上傳到服務端,網上有不少自定義的相機,也下載了不少,但是效果還是不滿意,所以決定自定義下,不多說了,直接上代碼:
public class CameraViews extends SurfaceView implements SurfaceHolder.Callback{
private String TAG=Camera.class.getName();
private Activity mActivity=null;
private Camera camera=null;
private SurfaceHolder holder=null;
/* 是否打開前置相機,true爲前置,false爲後置 */
private boolean mIsFrontCamera=false;
/是否開啓閃光燈 默認關閉閃光燈/
private String isOpenFlashMode= Camera.Parameters.FLASH_MODE_OFF;
private int curRotation=0;
private CameraCallback mCallback=null;
public CameraViews(Context context){
super(context);
initSurface();
}
public CameraViews(Context context, AttributeSet attrs) {
super(context, attrs);
initSurface();
}
public void setCurActivity(Activity activity){
this.mActivity=activity;
}
/**
* @Description: 初始化surface
* @Since:2015-8-11
* @Version:1.1.0
*/
private void initSurface(){
holder =getHolder();//獲得句柄
holder.addCallback(this);//添加回調
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不維護自己的緩衝區,等待屏幕渲染引擎將內容推送到用戶面前
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if(camera==null){
openCamera();
}
initCameraParams(mActivity);
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (Exception e) {
Toast.makeText(getContext(), "打開相機失敗", Toast.LENGTH_SHORT).show();
Log.e(TAG,e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
//try{
//camera.stopPreview();
//攝像頭畫面顯示在Surface上
//camera.setPreviewDisplay(holder);
//initCameraParams(mActivity);
//camera.startPreview();
//}catch(IOException e) {
// if (camera != null) camera.release();
//camera = null;
//}
//注意:這裏不能進行重新初始化相機,然後在預覽,不然進行橫縱拍照,照出來的圖片旋轉的角度會對應不上,所以這裏直接開啓預覽就好
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera=null;
holder=null;
}
@SuppressWarnings("unused")
private PictureCallback pictureCallback=new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
saveCameraImage(data, camera);
//這句話也很重要,是將你拍照成功後,圖片可以在相冊中查看到。(只不過我把這句話封裝到保存圖片中,保存圖片順帶加載到相冊)。
//MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");
//重新打開預覽圖,進行下一次的拍照準備
camera.startPreview();
}
};
/**
* @Description:設置相機預覽
* @Since:2015-8-11
* @Version:1.1.0
* @param activity
**/
public void setCameraPreView(){
if(camera!=null){
camera.stopPreview();
initCameraParams(mActivity);
try {
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (IOException e) {
Log.e(">>>>>","相機轉換失敗!"+e.getMessage());
}
}else{
Log.e(">>>>>","相機初始化失敗!");
}
}
/**
* @Description:保存拍照的圖片
* @Since:2015-8-11
* @Version:1.1.0
* @param data
* @param camera
*/
private void saveCameraImage(byte[] data, Camera camera) {
if(data==null){
Log.e(TAG, "獲取圖片流失敗,拍照失敗,請重試!");
return;
}
if(isFrontCamera()){
if(curRotation==90){
curRotation=270;
}else if(curRotation==270){
curRotation=90;
}
}
Bitmap thumbBM=null;
thumbBM=BitmapUtils.getInstance().save(mActivity,data,curRotation);
mCallback.onCameraCallback(thumbBM);
thumbBM=null;
}
/**
* @Description:設置相機參數
* @Since:2015-8-11
* @Version:1.1.0
*/
public void initCameraParams(Activity activity){
Camera.Parameters parameters = camera.getParameters();
// 選擇合適的預覽尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
if (sizeList.size()>0) {
Size cameraSize=sizeList.get(0);
//預覽圖片大小
parameters.setPreviewSize(cameraSize.width, cameraSize.height);
}
//設置生成的圖片大小
sizeList = parameters.getSupportedPictureSizes();
if (sizeList.size()>0) {
Size cameraSize=sizeList.get(0);
for (Size size : sizeList) {
//小於100W像素
if (size.width*size.height<100*10000) {
cameraSize=size;
break;
}
}
parameters.setPictureSize(cameraSize.width, cameraSize.height);
}
//設置圖片格式
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setJpegQuality(100);
parameters.setJpegThumbnailQuality(100);
//自動聚焦模式
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
parameters.setFlashMode(getIsOpenFlashMode());
//curRotation=getPreviewDegree();
screenDirectionListener();
//Log.e(">>>>>","curRotation:"+curRotation);
//parameters.setRotation(curRotation);//生成的圖片轉90°
//camera.setDisplayOrientation(curRotation);//預覽轉90°預覽圖片旋轉90°
//camera.setDisplayOrientation(getPreviewDegree());//預覽旋轉90°
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
public String getIsOpenFlashMode() {
return isOpenFlashMode;
}
/**
* @Description: 設置開啓閃光燈(重新預覽)
* @Since:2015-8-12
* @Version:1.1.0
* @param mIsOpenFlashMode
*/
public void setIsOpenFlashMode(boolean mIsOpenFlashMode) {
if(mIsOpenFlashMode)
this.isOpenFlashMode = Camera.Parameters.FLASH_MODE_ON;
else
this.isOpenFlashMode = Camera.Parameters.FLASH_MODE_OFF;;
setCameraPreView();//重新預覽相機
}
/**
* 根據當前照相機狀態(前置或後置),打開對應相機
*/
private boolean openCamera() {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
if(mIsFrontCamera){
Camera.CameraInfo cameraInfo=new CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, cameraInfo);
if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
try {
camera=Camera.open(i);
} catch (Exception e) {
camera =null;
return false;
}
}
}
}else {
try {
camera=Camera.open();
} catch (Exception e) {
camera =null;
return false;
}
}
return true;
}
/**
* @Description:獲取相機攝像頭個數
* @Since:2015-8-11
* @Version:1.1.0
* @return
*/
public int getCameraCount(){
return Camera.getNumberOfCameras();//得到攝像頭的個數
}
private boolean isFrontCamera(){
return mIsFrontCamera;
}
/**
* @Description:轉換前置和後置照相機
* @Since:2015-8-11
* @Version:1.1.0
* @return
*/
public boolean switchCamera(){
mIsFrontCamera=!mIsFrontCamera;
openCamera();
if(camera!=null){
initCameraParams(mActivity);
//updateCameraOrientation();
try {
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (IOException e) {
Log.e(">>>>>","相機轉換失敗!"+e.getMessage());
}
}
return mIsFrontCamera;
}
/**
* @Description: 拍照
* @Since:2015-8-31
* @Version:1.1.0
* @param mCameraCallback
*/
public void takePhoto(CameraCallback mCameraCallback){
try {
initSurface();
initCameraParams(mActivity);
camera.takePicture(null, null, pictureCallback);//將拍攝到的照片給自定義的對象
this.mCallback=mCameraCallback;
} catch (Exception e) {
Toast.makeText(mActivity,"初始化相機失敗!",Toast.LENGTH_SHORT).show();
}
}
public interface CameraCallback{
void onCameraCallback(Bitmap bitmap);
}
/**
* @Description: 監聽屏幕的旋轉方向
* @Since:2015-8-12
* @Version:1.1.0
*/
private void screenDirectionListener(){
OrientationEventListener mOrEventListener =new OrientationEventListener(getContext()) {
@Override
public void onOrientationChanged(int rotation) {
//getScreenDirect();
if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)||((rotation>=135)&&(rotation<=225))){////portrait
} else if (((rotation > 45) && (rotation < 135))||((rotation>225)&&(rotation<315))) {//landscape
}
if (((rotation >= 0) && (rotation <= 45)) || (rotation > 315)){//縱屏向上
rotation=90;
}else if ((rotation > 45) && (rotation <= 135)) {//橫屏向右
rotation=180;
}
else if ((rotation > 135) && (rotation <= 225)) {//縱屏向下
rotation=270;
}
else if((rotation > 225) && (rotation <= 315)) { //橫屏向左
rotation=0;
}else {
rotation=0;
}
curRotation=rotation;
}
};
mOrEventListener.enable();
}