今天在做手机摄像头自动对焦时出了一些问题,这里做个笔记记录一下。


注意事项:1、初始化Camera的代码中要加入下面两行代码

mCamera.autoFocus(myAutoFocusCallback);mCamera.cancelAutoFocus();
示例:
   
private void initCamera(SurfaceHolder holder) {        Log.i(TAG, "initCamera..");        if (mPreviewRunning) {            mCamera.stopPreview();        }        Camera.Parameters parameters;        try {            parameters = mCamera.getParameters();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();            return;        }        parameters.setPreviewSize(videoWidth, videoHight);        parameters.setPictureFormat(PixelFormat.JPEG);        parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);        SetCameraFPS(parameters);        setCameraDisplayOrientation(this, curCameraIndex, mCamera);        mCamera.setParameters(parameters);        int bufferSize = (((videoWidth | 0xf) + 1) * videoHight * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat())) / 8;        mCamera.addCallbackBuffer(new byte[bufferSize]);        mCamera.setPreviewCallbackWithBuffer(this);        try {            mCamera.setPreviewDisplay(holder);        } catch (Exception ex) {            // TODO Auto-generated catch block            if (null != mCamera) {                mCamera.release();                mCamera = null;            }            ex.printStackTrace();        }        mCamera.startPreview();        mCamera.autoFocus(myAutoFocusCallback);        mCamera.cancelAutoFocus();        mPreviewRunning = true;    }

myAutoFocusCallback相关代码:
   private Camera.AutoFocusCallback myAutoFocusCallback = null;...//自动聚焦变量回调        myAutoFocusCallback = new Camera.AutoFocusCallback() {            public void onAutoFocus(boolean success, Camera camera) {                if (success)//success表示对焦成功                {                    Log.i(TAG, "onAutoFocus succeed...");                    camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。                    initCamera(mSurfaceHolder);                    doAutoFocus();                } else {                    Log.i(TAG, "onAutoFocus failed...");                }            }        };

注意事项2:也是上面代码中的一个聚焦的方法doAutoFocus
//设置聚焦    private void doAutoFocus() {        parameters = mCamera.getParameters();        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);        mCamera.setParameters(parameters);        mCamera.autoFocus(new Camera.AutoFocusCallback() {            @Override            public void onAutoFocus(boolean success, Camera camera) {                if (success) {                    camera.cancelAutoFocus();// 只有加上了这一句,才会自动对焦。                    if (!Build.MODEL.equals("KORIDY H30")) {                        parameters = camera.getParameters();                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续自动对焦                        camera.setParameters(parameters);                    } else {                        parameters = camera.getParameters();                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);                        camera.setParameters(parameters);                    }                }            }        });    }

这里面有个注释是 “连续自动对焦”,如果不选择这个模式 只能实现一开始自动对焦一次 然后在远近变化就不对焦了


最后完整代码贴一份,后面在找这个代码就方便了 不用打开工程去找:

package com.star.surveillance.live;import android.Manifest;import android.annotation.SuppressLint;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.content.pm.PackageManager;import android.graphics.ImageFormat;import android.graphics.PixelFormat;import android.hardware.Camera;import android.media.AudioManager;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.os.Environment;import android.support.annotation.RequiresApi;import android.support.v4.app.ActivityCompat;import android.util.Log;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.WindowManager;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import com.star.star_common.util.ActivityStyleUtil;import com.star.star_common.util.ToastUtil;import com.star.star_common.view.StarTextView;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import static com.star.star_common.constants.StarConstants.TAG;public class RecordActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback {    private LinearLayout rightBtnsLL;    private FrameLayout playFL;    private StarTextView backTV;    private ImageView backIV;    private ImageView switchCameraIV;    private ImageView voiceIV;    private StarTextView topBackTV;    private RelativeLayout topTitleRL;    private RelativeLayout backRL;    private int previousVolume = 10;    private View main;    private MyVolumeReceiver mVolumeReceiver;    private Uri fileUri;    private Camera mCamera = null;    private Camera.AutoFocusCallback myAutoFocusCallback = null;    private SurfaceView mSurfaceView = null;    private SurfaceHolder mSurfaceHolder = null;    private static final int FRONT = 1;        //前置摄像头标记    private static final int BACK = 2;        //后置摄像头标记    private int currentCameraType = BACK;    //当前打开的摄像头标记    private int curCameraIndex = -1;    private boolean mPreviewRunning = false;    private final int videoWidth = 1280;    private final int videoHight = 720;    private int frameCount = 0;    private Camera.Parameters parameters;//相机参数    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ActivityStyleUtil.setStatusTransparentStyle(this, false);        main = getLayoutInflater().inflate(R.layout.activity_record, null);        main.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);    //屏幕常亮        setContentView(main);/*        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);        try {            fileUri = Uri.fromFile(createMediaFile()); // create a file to save the video        } catch (Exception e) {            e.printStackTrace();        }        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // set the image file name        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high        // start the Video Capture Intent        startActivityForResult(intent, 1);*/        int permission = ActivityCompat.checkSelfPermission(this,                android.Manifest.permission.READ_PHONE_STATE);        if (permission != PackageManager.PERMISSION_GRANTED) {            // We don't have permission so prompt the user            ActivityCompat.requestPermissions(this, new String[]{                    android.Manifest.permission.RECORD_AUDIO,                    android.Manifest.permission.READ_EXTERNAL_STORAGE,                    android.Manifest.permission.READ_PHONE_STATE,                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE,                    android.Manifest.permission.CAMERA,                    android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,                    android.Manifest.permission.INTERNET,                    android.Manifest.permission.ACCESS_NETWORK_STATE,                    android.Manifest.permission.ACCESS_WIFI_STATE,                    android.Manifest.permission.WAKE_LOCK,                    android.Manifest.permission.VIBRATE,                    android.Manifest.permission.SYSTEM_ALERT_WINDOW,            }, 1);        }        initView();        registerVolumeReceiver();    }    @Override    protected void onDestroy() {        super.onDestroy();        try {            if (mVolumeReceiver != null) {                unregisterReceiver(mVolumeReceiver);                mVolumeReceiver = null;            }        } catch (Exception e) {            e.printStackTrace();        }    }    private void initView() {        backIV = (ImageView) findViewById(R.id.surveillance_common_back_iv);        topTitleRL = (RelativeLayout) findViewById(R.id.surveillance_common_top_rl);        topTitleRL.setBackgroundResource(R.drawable.surveillance_record_back_bj);        topBackTV = (StarTextView) findViewById(R.id.surveillance_common_back_tv);        topBackTV.setText("手机录制");        playFL = (FrameLayout) findViewById(R.id.surveillance_record_fl);        backTV = (StarTextView) findViewById(R.id.surveillance_common_back_tv);        backRL = (RelativeLayout) findViewById(R.id.surveillance_common_back_rl);        backRL.setOnClickListener(mClickListener);        voiceIV = (ImageView) findViewById(R.id.surveillance_record_mute_iv);        voiceIV.setOnClickListener(mClickListener);        rightBtnsLL = (LinearLayout) findViewById(R.id.surveillance_record_right_btn_ll);        if (getCurrentVolume() == 0) {            voiceIV.setBackgroundResource(R.drawable.surveillance_record_mute);        }        mSurfaceView = (SurfaceView) findViewById(R.id.surface);        mSurfaceView.setOnClickListener(mClickListener);        mSurfaceHolder = mSurfaceView.getHolder();        mSurfaceHolder.addCallback(this);        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        switchCameraIV = (ImageView) findViewById(R.id.surveillance_record_switch_camera_iv);        switchCameraIV.setOnClickListener(mClickListener);        //自动聚焦变量回调        myAutoFocusCallback = new Camera.AutoFocusCallback() {            public void onAutoFocus(boolean success, Camera camera) {                if (success)//success表示对焦成功                {                    Log.i(TAG, "onAutoFocus succeed...");                    camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。                    initCamera(mSurfaceHolder);                    doAutoFocus();                } else {                    Log.i(TAG, "onAutoFocus failed...");                }            }        };    }    private View.OnClickListener mClickListener = new View.OnClickListener() {        @Override        public void onClick(View v) {            if (v.getId() == R.id.surveillance_record_mute_iv) {                if (getCurrentVolume() == 0) {                    voiceIV.setBackgroundResource(R.drawable.surveillance_record_voice);                } else {                    voiceIV.setBackgroundResource(R.drawable.surveillance_record_mute);                }                setStreamVolume();            } else if (v.getId() == R.id.surveillance_common_back_rl) {                onBackPressed();            } else if (v.getId() == R.id.surveillance_record_switch_camera_iv) {            } else if (v.getId() == R.id.surface) {                doAutoFocus();            }        }    };    public void setStreamVolume() {        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);        int volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);        if (volume == 0) {            am.setStreamVolume(AudioManager.STREAM_MUSIC, previousVolume, AudioManager.FLAG_PLAY_SOUND);        } else {            previousVolume = volume;            am.setStreamVolume(AudioManager.STREAM_MUSIC, 0, AudioManager.FLAG_PLAY_SOUND);        }    }    public int getCurrentVolume() {        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);        int volume = am.getStreamVolume(AudioManager.STREAM_MUSIC);        return volume;    }    //动态获取内存存储权限    public static void verifyStoragePermissions(Activity activity) {        // Check if we have write permission        int permission = ActivityCompat.checkSelfPermission(activity,                Manifest.permission.WRITE_EXTERNAL_STORAGE);        if (permission != PackageManager.PERMISSION_GRANTED) {            // We don't have permission so prompt the user            ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);        }    }    @Override    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {        switch (requestCode) {            case 1: {                // If request is cancelled, the result arrays are empty.                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                } else {                    ToastUtil.showLongToast("需要SD卡权限才可以使用此功能");                }                return;            }        }    }    @Override    public void onBackPressed() {        finish();    }    /**     * 注册当音量发生变化时接收的广播     */    private void registerVolumeReceiver() {        mVolumeReceiver = new MyVolumeReceiver();        IntentFilter filter = new IntentFilter();        filter.addAction("android.media.VOLUME_CHANGED_ACTION");        registerReceiver(mVolumeReceiver, filter);    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        Log.i(TAG, "surfaceCreated..");        try {            int CammeraIndex = findBackCamera();            Log.i(TAG, "BackCamera: " + CammeraIndex);            if (CammeraIndex == -1) {                CammeraIndex = findFrontCamera();                currentCameraType = FRONT;                switchCameraIV.setEnabled(false);                if (CammeraIndex == -1) {                    Log.i(TAG, "NO camera!!");                    return;                }            } else {                currentCameraType = BACK;            }            if (mCamera == null) {                mCamera = openCamera(currentCameraType);            }        } catch (Exception e) {            e.printStackTrace();        }    }    @SuppressLint("NewApi")    private Camera openCamera(int type) {        int frontIndex = -1;        int backIndex = -1;        int cameraCount = Camera.getNumberOfCameras();        Log.i(TAG, "cameraCount: " + cameraCount);        Camera.CameraInfo info = new Camera.CameraInfo();        for (int cameraIndex = 0; cameraIndex < cameraCount; cameraIndex++) {            Camera.getCameraInfo(cameraIndex, info);            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {                frontIndex = cameraIndex;            } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {                backIndex = cameraIndex;            }        }        currentCameraType = type;        if (type == FRONT && frontIndex != -1) {            curCameraIndex = frontIndex;            return Camera.open(frontIndex);        } else if (type == BACK && backIndex != -1) {            curCameraIndex = backIndex;            return Camera.open(backIndex);        }        return null;    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        Log.i(TAG, "surfaceChanged..");        initCamera(holder);        mCamera.cancelAutoFocus();// 只有加上了这一句,才会自动对焦        doAutoFocus();    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {    }    //Check if it has back camera    private int findBackCamera() {        int cameraCount = 0;        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();        cameraCount = Camera.getNumberOfCameras();        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {            Camera.getCameraInfo(camIdx, cameraInfo);            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {                return camIdx;            }        }        return -1;    }    //监听    //Check if it has front camera    private int findFrontCamera() {        int cameraCount = 0;        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();        cameraCount = Camera.getNumberOfCameras();        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {            Camera.getCameraInfo(camIdx, cameraInfo);            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {                return camIdx;            }        }        return -1;    }    /*it will call when surfaceChanged*/    private void initCamera(SurfaceHolder holder) {        Log.i(TAG, "initCamera..");        if (mPreviewRunning) {            mCamera.stopPreview();        }        Camera.Parameters parameters;        try {            parameters = mCamera.getParameters();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();            return;        }        parameters.setPreviewSize(videoWidth, videoHight);        parameters.setPictureFormat(PixelFormat.JPEG);        parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);        SetCameraFPS(parameters);        setCameraDisplayOrientation(this, curCameraIndex, mCamera);        mCamera.setParameters(parameters);        int bufferSize = (((videoWidth | 0xf) + 1) * videoHight * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat())) / 8;        mCamera.addCallbackBuffer(new byte[bufferSize]);        mCamera.setPreviewCallbackWithBuffer(this);        try {            mCamera.setPreviewDisplay(holder);        } catch (Exception ex) {            // TODO Auto-generated catch block            if (null != mCamera) {                mCamera.release();                mCamera = null;            }            ex.printStackTrace();        }        mCamera.startPreview();        mCamera.autoFocus(myAutoFocusCallback);        mCamera.cancelAutoFocus();        mPreviewRunning = true;    }    //设置相机显示的方向    private void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {        Camera.CameraInfo info = new Camera.CameraInfo();        Camera.getCameraInfo(cameraId, info);        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();        int degrees = 0;        switch (rotation) {            case Surface.ROTATION_0:                degrees = 0;                break;            case Surface.ROTATION_90:                degrees = 90;                break;            case Surface.ROTATION_180:                degrees = 180;                break;            case Surface.ROTATION_270:                degrees = 270;                break;        }        int result;        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {            result = (info.orientation + degrees) % 360;            result = (360 - result) % 360;        } else {            // back-facing            result = (info.orientation - degrees + 360) % 360;        }        Log.i(TAG, "curDegree: " + result);        camera.setDisplayOrientation(result);    }    private void SetCameraFPS(Camera.Parameters parameters) {        if (parameters == null) {            return;        }        int[] findRange = null;        int defFPS = 20 * 1000;        List fpsList = parameters.getSupportedPreviewFpsRange();        if (fpsList != null && fpsList.size() > 0) {            for (int i = 0; i < fpsList.size(); ++i) {                int[] range = fpsList.get(i);                if (range != null                        && Camera.Parameters.PREVIEW_FPS_MIN_INDEX < range.length                        && Camera.Parameters.PREVIEW_FPS_MAX_INDEX < range.length) {                    Log.i(TAG, "Camera index:" + i + " support min fps:" + range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]);                    if (findRange == null) {                        if (defFPS <= range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]) {                            findRange = range;                            Log.i(TAG, "Camera found appropriate fps, min fps:" + range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]                                    + " ,max fps:" + range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);                        }                    }                }            }        }        if (findRange != null) {            parameters.setPreviewFpsRange(findRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], findRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);        }    }    @Override    public void onPreviewFrame(byte[] data, Camera camera) {        frameCount++;        if (frameCount % 3000 == 0) {            Log.i("OnPre", "gc+");            System.gc();            Log.i("OnPre", "gc-");        }        if (data == null) {            Camera.Parameters params = camera.getParameters();            Camera.Size size = params.getPreviewSize();            int bufferSize = (((size.width | 0x1f) + 1) * size.height * ImageFormat.getBitsPerPixel(params.getPreviewFormat())) / 8;            camera.addCallbackBuffer(new byte[bufferSize]);        } else {            camera.addCallbackBuffer(data);        }    }    /**     * 处理音量变化时的界面显示     *     * @author long     */    private class MyVolumeReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            if (intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")) {                if (getCurrentVolume() == 0) {                    voiceIV.setBackgroundResource(R.drawable.surveillance_record_mute);                } else {                    voiceIV.setBackgroundResource(R.drawable.surveillance_record_voice);                }            }        }    }    @Override    protected void onResume() {        super.onResume();    }    @Override    protected void onStop() {        super.onStop();    }    /* 创建保存录制得到的视频文件     *     * @return     * @throws IOException     */    private File createMediaFile() throws IOException {        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(                    Environment.DIRECTORY_MOVIES), "CameraDemo");            if (!mediaStorageDir.exists()) {                if (!mediaStorageDir.mkdirs()) {                    Log.d(TAG, "failed to create directory");                    return null;                }            }            // Create an image file name            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());            String imageFileName = "VID_" + timeStamp;            String suffix = ".mp4";            File mediaFile = new File(mediaStorageDir + File.separator + imageFileName + suffix);            return mediaFile;        } else {            // 当前不可用        }        return null;    }    //设置聚焦    private void doAutoFocus() {        parameters = mCamera.getParameters();        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);        mCamera.setParameters(parameters);        mCamera.autoFocus(new Camera.AutoFocusCallback() {            @Override            public void onAutoFocus(boolean success, Camera camera) {                if (success) {                    camera.cancelAutoFocus();// 只有加上了这一句,才会自动对焦。                    if (!Build.MODEL.equals("KORIDY H30")) {                        parameters = camera.getParameters();                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续自动对焦                        camera.setParameters(parameters);                    } else {                        parameters = camera.getParameters();                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);                        camera.setParameters(parameters);                    }                }            }        });    }}

里面引用的库不必关心,参考里面摄像头部分的流程和逻辑即可。

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. PopupWindow位置
  3. Android(安卓)Studio 设置内存大小及原理
  4. AlertDialog使用自定义的布局
  5. java.io.IOException:Can't read [F:\..\android-support-v4.ja
  6. android之解析包时出现错误(二)
  7. android之点击回退键俩次退出程序
  8. Android之Handler的post注意事项
  9. Android仿硅谷商城实现购物车实例代码

随机推荐

  1. Android(安卓)Alarm驱动源代码分析(Alarm.
  2. Android(安卓)USB配件模式
  3. android设备连接到pc进行应用程序调试
  4. Android简明开发教程九:创建应用程序框架
  5. Android各版本市占率:果冻豆Android4.1遥
  6. Android(安卓)免安装应用
  7. 国内最全的Android市场,最全Android软件商
  8. 在Android设备上运行纯java代码
  9. Android服务注册完整过程源码分析
  10. Android(安卓)集成Chrome 浏览器内核 Cro