SurfaceHolder CallBack没有触发

时间:2015-10-11 05:41:11

标签: android callback surfaceview

以下课程将使用前置摄像头拍摄照片并将其存储在Android画廊中:

  public class TakePicture extends Activity implements SurfaceHolder.Callback {
// a variable to store a reference to the Image View at the main.xml file
  // private ImageView iv_image;
 // a variable to store a reference to the Surface View at the main.xml file
private SurfaceView sv;

// a bitmap to display the captured image
private Bitmap bmp;
FileOutputStream fo;

// Camera variables
// a surface holder
private SurfaceHolder sHolder;
// a variable to control the camera
private Camera mCamera;
// the camera parameters
private Camera.Parameters parameters;
private String FLASH_MODE;
private boolean isFrontCamRequest = false;
private Camera.Size pictureSize;

/** Called when the activity is first created. */
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.background);

    // check if this device has a camera

        // get the Image View at the main.xml file
        // iv_image = (ImageView) findViewById(R.id.imageView);

        // get the Surface View at the main.xml file
        Bundle extras = getIntent().getExtras();
        FLASH_MODE = "FLASH_MODE_OFF";
        boolean front_cam_req = true;
        isFrontCamRequest = front_cam_req;

        sv = (SurfaceView) findViewById(R.id.camera_preview);

        // Get a surface
        sHolder = sv.getHolder();

        // add the callback interface methods defined below as the Surface
        // View
        // callbacks
        sHolder.addCallback(this);

        // tells Android that this surface will have its data constantly
        // replaced
        if (Build.VERSION.SDK_INT < 11)
            sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);



}

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA)) {
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

/** Check if this device has front camera */
private boolean checkFrontCamera(Context context) {
    if (context.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA_FRONT)) {
        // this device has front camera
        return true;
    } else {
        // no front camera on this device
        return false;
    }
}

public static Camera getCameraInstance() {
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    } catch (Exception e) {
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // get camera parameters
    if (mCamera != null) {
        parameters = mCamera.getParameters();
        if (FLASH_MODE == null || FLASH_MODE.isEmpty()) {
            FLASH_MODE = "auto";
        }
        parameters.setFlashMode(FLASH_MODE);
        pictureSize = getBiggesttPictureSize(parameters);
        if (pictureSize != null)
            parameters
                    .setPictureSize(pictureSize.width, pictureSize.height);
        // set camera parameters
        mCamera.setParameters(parameters);

        mCamera.startPreview();

        // sets what code should be executed after the picture is taken
        Camera.PictureCallback mCall = new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                // decode the data obtained by the camera into a Bitmap
                Log.d("ImageTakin", "Done");

                bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                if (bmp != null)
                    bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);


                //FOR GALLERY STORAGE ---- TEST
                File androidVidGalleryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                File imagesFolder = new File(androidVidGalleryPath+"/Guardian");
                if (!imagesFolder.exists())
                    imagesFolder.mkdirs(); // <----


                SharedPreferences pref = getSharedPreferences("MyPref", Context.MODE_PRIVATE);
                final SharedPreferences.Editor editor = pref.edit();

                Integer guardianCount = pref.getInt("guardianCountimg",0);

                File image = new File(androidVidGalleryPath+"/Guardian/img_"+String.valueOf(guardianCount)+".jpg");

                editor.putInt("guardianCountimg",guardianCount+1).commit();


                // write the bytes in file
                try {
                    fo = new FileOutputStream(image);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                }
                try {
                    fo.write(bytes.toByteArray());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                }

                // remember close de FileOutput
                try {
                    fo.close();
                    //sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"
                      //      + Environment
                        //    .getExternalStorageDirectory())));
                    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(image)));

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                }
                if (mCamera != null) {
                    mCamera.stopPreview();
                    // release the camera
                    mCamera.release();
                }
                Toast.makeText(getApplicationContext(),
                        "Invalid login\n\nRegistered owner will be notified!", Toast.LENGTH_LONG)
                        .show();
                if (bmp != null) {
                    bmp.recycle();
                    bmp = null;
                    System.gc();
                }
                TakePicture.this.finish();

            }
        };

        mCamera.takePicture(null, null, mCall);
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw the preview.
    if (isFrontCamRequest) {

        // set flash 0ff
        FLASH_MODE = "off";
        // only for gingerbread and newer versions
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            mCamera = openFrontFacingCameraGingerbread();
            try {
                mCamera.setPreviewDisplay(holder);

            } catch (IOException exception) {
                mCamera = null;
                Toast.makeText(getApplicationContext(),
                        "API dosen't support front camera",
                        Toast.LENGTH_LONG).show();
                TakePicture.this.finish();
            }
        } else {
            if (checkFrontCamera(getApplicationContext())) {
                mCamera = openFrontFacingCameraGingerbread();
                try {
                    mCamera.setPreviewDisplay(holder);

                } catch (IOException exception) {
                    mCamera = null;
                    Toast.makeText(getApplicationContext(),
                            "API dosen't support front camera",
                            Toast.LENGTH_LONG).show();
                    TakePicture.this.finish();
                }
            }/*
         * else { // API dosen't support front camera or no front camera
         * Log.d("Camera",
         * "API dosen't support front camera or no front camera");
         * Toast.makeText( getApplicationContext(),
         * "API dosen't support front camera or no front camera",
         * Toast.LENGTH_LONG).show();
         *
         * finish(); }
         */

        }
    } else {
        mCamera = getCameraInstance();
        try {
            mCamera.setPreviewDisplay(holder);

        } catch (Exception exception) {
            mCamera = null;
        }
    }

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // stop the preview
/*
 * mCamera.stopPreview(); // release the camera mCamera.release();
 */
    // unbind the camera from this object
    mCamera = null;
}

private Camera openFrontFacingCameraGingerbread() {
    int cameraCount = 0;
    Camera cam = null;
    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) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e("Camera",
                        "Camera failed to open: " + e.getLocalizedMessage());
                Toast.makeText(getApplicationContext(),
                        "Front Camera failed to open", Toast.LENGTH_LONG)
                        .show();
            }
        }
    }
    return cam;
}

@Override
protected void onDestroy() {
    Intent intent = new Intent("custom-event-name");
    // You can also include some extra data.
    intent.putExtra("message", "This is my message!");
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

    super.onDestroy();
}

private Camera.Size getBiggesttPictureSize(Camera.Parameters parameters) {
    Camera.Size result = null;

    for (Camera.Size size : parameters.getSupportedPictureSizes()) {
        if (result == null) {
            result = size;
        } else {
            int resultArea = result.width * result.height;
            int newArea = size.width * size.height;

            if (newArea > resultArea) {
                result = size;
            }
        }
    }

    return (result);
}

}

问题是我想这样做而不必使用以下方式开始新活动:

    Intent intent = new Intent(MainActivity.this,TakePicture.class);
    startActivity(intent);

相反,我已经在on create部分将此活动的代码添加到名为takePic()的方法中,并移动了所需的方法,如下所示:

  public void takePic(){

    FLASH_MODE = "FLASH_MODE_OFF";
    boolean front_cam_req = true;
    isFrontCamRequest = front_cam_req;
    sv = (SurfaceView) findViewById(R.id.camera_preview);
    sHolder = sv.getHolder();
    sHolder.addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, acquire the camera and tell it where
            // to draw the preview.
            if (isFrontCamRequest) {

                // set flash 0ff
                FLASH_MODE = "off";
                // only for gingerbread and newer versions
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
                    mCamera = openFrontFacingCameraGingerbread();
                    try {
                        mCamera.setPreviewDisplay(holder);

                    } catch (IOException exception) {
                        mCamera = null;
                        Toast.makeText(getApplicationContext(),
                                "API dosen't support front camera",
                                Toast.LENGTH_LONG).show();
                        //TakePicture.this.finish();
                    }
                } else {
                    if (checkFrontCamera(getApplicationContext())) {
                        mCamera = openFrontFacingCameraGingerbread();
                        try {
                            mCamera.setPreviewDisplay(holder);

                        } catch (IOException exception) {
                            mCamera = null;
                            Toast.makeText(getApplicationContext(),
                                    "API dosen't support front camera",
                                    Toast.LENGTH_LONG).show();
                            //TakePicture.this.finish();
                        }
                    }/*
         * else { // API dosen't support front camera or no front camera
         * Log.d("Camera",
         * "API dosen't support front camera or no front camera");
         * Toast.makeText( getApplicationContext(),
         * "API dosen't support front camera or no front camera",
         * Toast.LENGTH_LONG).show();
         *
         * finish(); }
         */

                }
            } else {
                mCamera = getCameraInstance();
                try {
                    mCamera.setPreviewDisplay(holder);

                } catch (Exception exception) {
                    mCamera = null;
                }
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            // get camera parameters
            if (mCamera != null) {
                parameters = mCamera.getParameters();
                if (FLASH_MODE == null || FLASH_MODE.isEmpty()) {
                    FLASH_MODE = "auto";
                }
                parameters.setFlashMode(FLASH_MODE);
                pictureSize = getBiggesttPictureSize(parameters);
                if (pictureSize != null)
                    parameters
                            .setPictureSize(pictureSize.width, pictureSize.height);
                // set camera parameters
                mCamera.setParameters(parameters);

                mCamera.startPreview();

                // sets what code should be executed after the picture is taken
                Camera.PictureCallback mCall = new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        // decode the data obtained by the camera into a Bitmap
                        Log.d("ImageTakin", "Done");

                        bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                        if (bmp != null)
                            bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);


                        //FOR GALLERY STORAGE ---- TEST
                        File androidVidGalleryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                        File imagesFolder = new File(androidVidGalleryPath+"/Guardian");
                        if (!imagesFolder.exists())
                            imagesFolder.mkdirs(); // <----

                        SharedPreferences pref = getSharedPreferences("MyPref", Context.MODE_PRIVATE);
                        final SharedPreferences.Editor editor = pref.edit();

                        Integer guardianCount = pref.getInt("guardianCountimg",0);

                        File image = new File(androidVidGalleryPath+"/Guardian/img_"+String.valueOf(guardianCount)+".jpg");

                        editor.putInt("guardianCountimg",guardianCount+1).commit();


                        // write the bytes in file
                        try {
                            fo = new FileOutputStream(image);
                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                        }
                        try {
                            fo.write(bytes.toByteArray());
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                        }

                        // remember close de FileOutput
                        try {
                            fo.close();
                            //sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"
                            //      + Environment
                            //    .getExternalStorageDirectory())));
                            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(image)));

                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                        }
                        if (mCamera != null) {
                            mCamera.stopPreview();
                            // release the camera
                            mCamera.release();
                        }
                        Toast.makeText(getApplicationContext(),
                                "Invalid login\n\nRegistered owner will be notified!", Toast.LENGTH_LONG)
                                .show();
                        if (bmp != null) {
                            bmp.recycle();
                            bmp = null;
                            System.gc();
                        }
                        //TakePicture.this.finish();



                    }
                };

                mCamera.takePicture(null, null, mCall);
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            mCamera = null;
        }
    });

    // tells Android that this surface will have its data constantly
    // replaced
    if (Build.VERSION.SDK_INT < 11)
        sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA)) {
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

/** Check if this device has front camera */
private boolean checkFrontCamera(Context context) {
    if (context.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA_FRONT)) {
        // this device has front camera
        return true;
    } else {
        // no front camera on this device
        return false;
    }
}

public static Camera getCameraInstance() {
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    } catch (Exception e) {
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}



private Camera openFrontFacingCameraGingerbread() {
    int cameraCount = 0;
    Camera cam = null;
    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) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e("Camera",
                        "Camera failed to open: " + e.getLocalizedMessage());
                Toast.makeText(getApplicationContext(),
                        "Front Camera failed to open", Toast.LENGTH_LONG)
                        .show();
            }
        }
    }
    return cam;
}

@Override
protected void onDestroy() {
    Intent intent = new Intent("custom-event-name");
    // You can also include some extra data.
    intent.putExtra("message", "This is my message!");
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

    super.onDestroy();
}

private Camera.Size getBiggesttPictureSize(Camera.Parameters parameters) {
    Camera.Size result = null;

    for (Camera.Size size : parameters.getSupportedPictureSizes()) {
        if (result == null) {
            result = size;
        } else {
            int resultArea = result.width * result.height;
            int newArea = size.width * size.height;

            if (newArea > resultArea) {
                result = size;
            }
        }
    }

    return (result);
}

使用takePic()方法时,在我返回主屏幕并重新打开应用程序之前不会拍照。

为什么我打电话给takePic()时没有拍到照片?

1 个答案:

答案 0 :(得分:0)

SurfaceView的Surface是在onCreate()完成后的某个时间异步创建的。您的takePic()方法正在建立回调,但如果在创建Surface之后这样做,那么回调将不会被调用,直到下次创建Surface时(例如旋转设备时) )。

将捕获绑定到预览表面创建回调似乎有点落后,特别是在SurfaceView的quirky nature时。