长按关闭按钮

时间:2017-02-05 12:23:00

标签: android android-camera android-camera2

请帮忙。有没有办法使用Camera API(Android SDK 19和17之间的版本)使相机在长按关闭按钮拍照之前对焦?

换句话说,我长按相机按钮(我的意思是它可能是相机按钮或屏幕上的按钮)焦点必须开始,在第一秒我释放该按钮它应该拍照

请帮忙。

1 个答案:

答案 0 :(得分:0)

好的,对于这个功能,两个方法是重要的onTouchEvent(我可以检测释放按钮)和setOnLongClickListener(以检测拍摄照片的长按按钮)。在下面的代码中,我创建了一个自定义视图(名为DrawCameraOptions类),它在SurfaceView上方的屏幕上绘制一个红色圆圈,另一个自定义视图(名为DrawingRectForFocalisationAreaView类)在焦点区域的SurfaceView上绘制一个rect。

  

fragment_take_picture.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <customs.cameras.DrawingRectForFocalisationAreaView
        android:id="@+id/drawingFocusRectangle_FragmentTakePicture"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <customs.cameras.DrawCameraOptions
        android:id="@+id/takePicture_FragmentTakePicture2"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@android:color/transparent"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>
  

UpdateDrawingFocusAreaRect接口

package network.callbacks;

import android.graphics.Rect;
import android.hardware.Camera;

/**
 * Created by EmiG on 02.02.2017.
 */

public interface UpdateDrawingFocusAreaRect {

    public void repaintRectFocusArea(final Rect touchRect);

    public void takePictureOnLongPress();
}
  

DrawCameraOptions类

package customs.cameras;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import network.callbacks.UpdateDrawingFocusAreaRect;

/**
 * Created by EmiG on 18.01.2017.
 */

public class DrawCameraOptions extends View {

    private Paint paint;
    private UpdateDrawingFocusAreaRect callback;
    private static final String TAG="TakePictureFragment2";

    public DrawCameraOptions(Context context) {
        super(context);

        this.initComponets();
    }

    public void setCallback(UpdateDrawingFocusAreaRect callback) {
        this.callback = callback;
    }

    public DrawCameraOptions(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.initComponets();
    }

    public DrawCameraOptions(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.initComponets();
    }

    private void initComponets()
    {
        this.paint=new Paint(paint.ANTI_ALIAS_FLAG);
        this.paint.setStyle(Paint.Style.FILL_AND_STROKE);
        this.paint.setColor(Color.RED);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);

        final int width=getWidth() - getPaddingLeft() - getPaddingRight();//of the view
        final int height=getHeight() - getPaddingTop() - getPaddingBottom();
        final int cx=width/2 + getPaddingLeft();
        final int cy=height/2 + getPaddingTop();
        final float diameter= Math.min(width, height) - paint.getStrokeWidth();
        final float radious=diameter/2;
        canvas.drawCircle(cx,cy,radious,this.paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                Log.i(TAG,"ACTION_UP");
                if(null!=this.callback)
                {
                    this.callback.takePictureOnLongPress();
                }
                break;
        }
        return super.onTouchEvent(event);
    }
}
  

DrawingRectForFocalisationAreaView类

package customs.cameras;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by EmiG on 25.01.2017.
 */

public class DrawingRectForFocalisationAreaView extends View {

    private Paint drawingPaint;

    boolean haveTouch;
    private Rect touchArea;
    private static final int RECT_DIMENSIONS=50;

    public DrawingRectForFocalisationAreaView(Context context) {
        super(context);

        this.init();
    }

    public DrawingRectForFocalisationAreaView(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.init();
    }

    public DrawingRectForFocalisationAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.init();
    }

    private void init()
    {
        this.drawingPaint = new Paint();
        this.drawingPaint.setColor(Color.RED);
        this.drawingPaint.setStyle(Paint.Style.STROKE);
        this.drawingPaint.setStrokeWidth(2);
        this.haveTouch = false;
    }

    public void setHaveTouch(boolean t, Rect tArea){
        this.drawingPaint.setColor(Color.RED);
        this.haveTouch = t;
        this.touchArea = tArea;
    }

    public void validateFocus()
    {
        if(Color.RED == this.drawingPaint.getColor())
        {
            this.drawingPaint.setColor(Color.GREEN);
            this.haveTouch=true;
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if(this.haveTouch && null!=canvas&& null!=this.drawingPaint){

            canvas.drawRect(this.touchArea.left-RECT_DIMENSIONS, this.touchArea.top-RECT_DIMENSIONS, this.touchArea.right+RECT_DIMENSIONS, this.touchArea.bottom+RECT_DIMENSIONS, this.drawingPaint);
            this.haveTouch=false;
        }
    }
}
  

TakePictureFragment2类

public class TakePictureFragment2 extends Fragment implements SurfaceHolder.Callback, View.OnTouchListener, UpdateDrawingFocusAreaRect {

    private static final String TAG = TakePictureFragment2.class.getSimpleName();

    //region Focus variabiles
    private boolean bIsPictureTaking, bIsAutoFocusStarted, bIsAutoFocused, USE_AUTOFOCUS, isFocusated, isLongPressed, canTakePicture;
    private static final int FOCUS_AREA_SIZE = 300;
    //endregion

    private boolean camCondition = false;  // conditional variable for camera preview checking and set to false

    //region Camera object
    private Camera camera;
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;

    private Camera.PictureCallback jpegCallback;
    //endregion

    //region Execute multiple calculation functionality for drawing
    private ThreadPoolExecutor threadPoolExecutor;
    public static final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
    //endregion

    //region Custom Objects that draw on the screen
    private DrawCameraOptions takePictureButton;// Draw shuttbutton for capture image
    //Desenare pe  ecran punct de focalizare
    private DrawingRectForFocalisationAreaView drawingRectangleOnScreen;//Draw blue rectangle on focus area
    //endregion

    //region Fragent methods
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView()");
        View view = inflater.inflate(R.layout.fragment_take_picture, container, false);
        if (null != view) {
            return view;
        }

        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.i(TAG, "onActivityCreated()");


        this.initOnTouchListener();
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i(TAG, "onResume()");

        this.initComponents();

        if (null != camera) {
            try {
                camera.setPreviewDisplay(surfaceHolder); // setting preview of camera
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
    //endregion




//region Initial Components
    private void initOnTouchListener() {
        if (null != this.getView()) {
            this.getView().setOnTouchListener(TakePictureFragment2.this);
        }
    }

    private void initComponents() {
        if (null != getView()) {

            this.drawingRectangleOnScreen = (DrawingRectForFocalisationAreaView) getView().findViewById(R.id.drawingFocusRectangle_FragmentTakePicture);

            takePictureButton = (DrawCameraOptions) getView().findViewById(R.id.takePicture_FragmentTakePicture2);
            takePictureButton.setCallback(TakePictureFragment2.this);


            takePictureButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i(TAG,"Simple click");

                    camera.takePicture(null, null, jpegCallback);
                }
            });

            takePictureButton.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    Log.i(TAG,"Long click");
                    final Context context=getView().getContext();
                    isLongPressed=true;
                    synchronized (this) {
                        if (camera != null) {
                            camera.cancelAutoFocus();
                            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
                                if (!bIsPictureTaking && !bIsAutoFocusStarted) {
                                    bIsAutoFocusStarted = true;
                                    new AsyncTask<Void, Void, Void>() {
                                        @Override
                                        protected Void doInBackground(Void... params) {
                                            try {
                                                Camera.Parameters parameters = camera.getParameters();
                                                if (parameters.getMaxNumMeteringAreas() > 0) {
                                                    Log.i(TAG, "fancy !");
                                                    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
                                                    Point screenDsiplay=new Point();
                                                    display.getSize(screenDsiplay);
                                                    Rect rect = calculateFocusArea(screenDsiplay.x/2, screenDsiplay.y/2);
                                                    display=null;
                                                    screenDsiplay=null;
                                                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                                                    List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
                                                    meteringAreas.add(new Camera.Area(rect, 1000));
                                                    parameters.setFocusAreas(meteringAreas);

                                                    camera.setParameters(parameters);
                                                    camera.autoFocus(mAutoFocusTakePictureCallback);
                                                } else {
                                                    camera.autoFocus(mAutoFocusTakePictureCallback);
                                                }
                                                bIsAutoFocusStarted = false;
                                            } catch (Exception e) {
                                                Log.e(TAG, "Error " + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            System.gc();
                                            return null;
                                        }
                                    }.execute((Void[]) null);
                                }
                            } else {
                                if (!bIsPictureTaking && !bIsAutoFocusStarted) {
                                    bIsAutoFocusStarted = true;
                                    new AsyncTask<Void, Void, Void>() {
                                        @Override
                                        protected Void doInBackground(Void... params) {
                                            try {
                                                Camera.Parameters parameters = camera.getParameters();
                                                if (parameters.getMaxNumMeteringAreas() > 0) {
                                                    Log.i(TAG, "fancy !");
                                                    Display display2 = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
                                                    Point screenDsiplay2=new Point();
                                                    display2.getSize(screenDsiplay2);
                                                    Rect rect = calculateFocusArea(screenDsiplay2.x/2, screenDsiplay2.y/2);
                                                    display2=null;
                                                    screenDsiplay2=null;

                                                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                                                    List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
                                                    meteringAreas.add(new Camera.Area(rect, 1000));
                                                    parameters.setFocusAreas(meteringAreas);

                                                    camera.setParameters(parameters);
                                                    camera.autoFocus(mAutoFocusTakePictureCallback);
                                                } else {
                                                    camera.autoFocus(mAutoFocusTakePictureCallback);
                                                }
                                                bIsAutoFocusStarted = false;

                                            } catch (Exception e) {
                                                Log.e(TAG, "Error " + e.getMessage());
                                                e.printStackTrace();
                                            }

                                            System.gc();
                                            return null;
                                        }
                                    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
                                }
                            }
                        }
                    }

                    return true;
                }
            });


            surfaceView = (SurfaceView) getView().findViewById(R.id.surfaceView);
            surfaceHolder = surfaceView.getHolder();
            // deprecated setting, but required on Android versions prior to 3.0
            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            surfaceHolder.addCallback(this);


            jpegCallback = new Camera.PictureCallback() {
                public void onPictureTaken(final byte[] data, Camera camera) {
                    USE_AUTOFOCUS=false;
                    canTakePicture=false;
                    final Context context = getView().getContext();
                    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
                        new AsyncTask<Void, Void, Void>() {
                            @Override
                            protected Void doInBackground(Void... params) {
                                bIsPictureTaking = true;  //set it to true to avoid onKeyDown dispatching during taking picture. it may be time-consuming
                                bIsAutoFocused = false; //reset to false
                                bIsAutoFocusStarted = false; //reset to false

                                FileOutputStream outStream = null;
                                try {
                                    final GregorianCalendar gregorianCalendar = new GregorianCalendar();
                                    gregorianCalendar.setTime(new Date());
                                    final StringBuffer stringBufferFileName = new StringBuffer();
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.YEAR));
                                    stringBufferFileName.append("_");
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.MONTH) + 1);
                                    stringBufferFileName.append("_");
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.DAY_OF_MONTH) + 1);

                                    final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "Rompetrol", stringBufferFileName.toString());
                                    if (!root.exists()) {
                                        root.mkdirs();
                                    }
                                    final File gpxfile = new File(root, System.currentTimeMillis() + ".jpg");


                                    outStream = new FileOutputStream(gpxfile);
                                    outStream.write(data);
                                    outStream.close();
                                    Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);

                                    final AudioManager meng = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                                    int volume = meng.getStreamVolume(AudioManager.STREAM_NOTIFICATION);

                                    if (volume != 0) {
                                        final MediaPlayer _shootMP = MediaPlayer.create(context, Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));
                                        _shootMP.start();
                                    }

                                    bIsPictureTaking = false;
                                    JSONObject jsonObjecte = new JSONObject();
                                    try {
                                        jsonObjecte.put(EventBusMessages.OPERATION_TO_PERFORM.getkey(), EventBusMessages.CHANGE_FRAGMENT.getkey());
                                        jsonObjecte.put(EventBusMessages.CHANGE_FRAGMENT.getkey(), FragmentList.DISPLAY_PICTURE_FRAGMENT.getKey());
                                        jsonObjecte.put(EventBusMessages.PICTURE_PATH.getkey(), gpxfile.getAbsolutePath());

                                        EventBus.getDefault().post(jsonObjecte);
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }

                                } catch (Exception e) {
                                    e.printStackTrace();
                                }

                                return null;
                            }
                        }.execute((Void[]) null);
                    }
                    else
                    {
                        new AsyncTask<Void, Void, Void>() {
                            @Override
                            protected Void doInBackground(Void... params) {
                                bIsPictureTaking = true;  //set it to true to avoid onKeyDown dispatching during taking picture. it may be time-consuming
                                bIsAutoFocused = false; //reset to false
                                bIsAutoFocusStarted = false; //reset to false

                                FileOutputStream outStream = null;
                                try {
                                    final GregorianCalendar gregorianCalendar = new GregorianCalendar();
                                    gregorianCalendar.setTime(new Date());
                                    final StringBuffer stringBufferFileName = new StringBuffer();
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.YEAR));
                                    stringBufferFileName.append("_");
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.MONTH) + 1);
                                    stringBufferFileName.append("_");
                                    stringBufferFileName.append(gregorianCalendar.get(Calendar.DAY_OF_MONTH) + 1);

                                    final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "Rompetrol", stringBufferFileName.toString());
                                    if (!root.exists()) {
                                        root.mkdirs();
                                    }
                                    final File gpxfile = new File(root, System.currentTimeMillis() + ".jpg");


                                    outStream = new FileOutputStream(gpxfile);
                                    outStream.write(data);
                                    outStream.close();
                                    Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);

                                    final AudioManager meng = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                                    int volume = meng.getStreamVolume(AudioManager.STREAM_NOTIFICATION);

                                    if (volume != 0) {
                                        final MediaPlayer _shootMP = MediaPlayer.create(context, Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));
                                        _shootMP.start();
                                    }

                                    bIsPictureTaking = false;
                                    JSONObject jsonObjecte = new JSONObject();
                                    try {
                                        jsonObjecte.put(EventBusMessages.OPERATION_TO_PERFORM.getkey(), EventBusMessages.CHANGE_FRAGMENT.getkey());
                                        jsonObjecte.put(EventBusMessages.CHANGE_FRAGMENT.getkey(), FragmentList.DISPLAY_PICTURE_FRAGMENT.getKey());
                                        jsonObjecte.put(EventBusMessages.PICTURE_PATH.getkey(), gpxfile.getAbsolutePath());

                                        EventBus.getDefault().post(jsonObjecte);
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }

                                } catch (Exception e) {
                                    e.printStackTrace();
                                }

                                return null;
                            }
                        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,(Void[]) null);
                    }

                    // stop preview before making changes
                    try {
                        camera.stopPreview();
                        surfaceView.invalidate();
                        surfaceHolder = null;
                    } catch (Exception e) {
                        // ignore: tried to stop a non-existent preview
                    }
                }
            };


            this.threadPoolExecutor = new ThreadPoolExecutor(
                    NUMBER_OF_CORES * 2,
                    NUMBER_OF_CORES * 2,
                    20L,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>());

            this.USE_AUTOFOCUS = false;
            this.bIsPictureTaking = false;  //set it to true to avoid onKeyDown dispatching during taking picture. it may be time-consuming
            this.bIsAutoFocused = false; //reset to false
            this.bIsAutoFocusStarted = false; //reset to false
            this.isLongPressed=false;//reset to false
            this.canTakePicture=false;//reset to false
        }
    }
    //endregion


public void repaintRectFocusArea(final Rect touchRect) {
    if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
        drawingRectangleOnScreen.setHaveTouch(true, touchRect);
        drawingRectangleOnScreen.invalidate();
    } else {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                drawingRectangleOnScreen.setHaveTouch(true, touchRect);
                drawingRectangleOnScreen.invalidate();
            }
        });
    }
}


public void takePictureOnLongPress() {
    if(this.isLongPressed)
    {
        Log.i(TAG,"ACTION_BUTTON_RELEASE");
        this.isLongPressed=false;
        this.canTakePicture=true;
        camera.takePicture(null, null, jpegCallback);
    }
}

请原谅我的错误代码写作。