Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義相機之Camera1

Android自定義相機之Camera1

編輯:關於Android編程

一、概述

本章節主要講述使用android.hardware.Camera類來實現自定義相機的流程,雖然在api21中該類已被廢棄,有了一套新的CameraDevice方法,但是為了向下兼容我們還是可以學習一下Camera1的使用。

如有錯誤或優化之處,歡迎留言指導。

二、具體實現

首先介紹下如何判斷是否支持照相機功能,代碼如下:

private boolean checkCamera(Context context) {
    // 可修改參數來判斷設備是否支持ble等其他功能
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        return true; // 支持Camera功能
    } else {
        return false;
    }
}

獲取一個Camera對象

private Camera getCamera() {
    Camera camera = null;
    try {
        camera = Camera.open();
    } catch (Exception e) {
        Log.e(TAG, "getCamera: Camera.open failed!");
    }
    return camera;
}

我們通過SurfaceView來預覽照相機畫面,需要獲取SurfaceHolder並添加回調

mPreView = (SurfaceView) findViewById(R.id.preview);
mHolder = mPreView.getHolder();
mHolder.addCallback(this); // 實現SurfaceHolder.Callback接口
mPreView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mCamera != null) {
            // 照相機自動對焦功能
            mCamera.autoFocus(null);
        }
    }
});

綁定Camera和SurfaceHolder,然後開始預覽畫面

private void setStartPreview(Camera camera, SurfaceHolder holder) {
    try {
        camera.setPreviewDisplay(holder); // 綁定Camera和SurfaceHolder
        camera.setDisplayOrientation(90); // 旋轉90度才是正常畫面
        camera.startPreview();
    } catch (IOException e) {
        Log.e(TAG, "setStartPreview: setPreviewDisplay error");
    }
}

在使用完相機後需要釋放相機資源,同時我們要注意把相機和活動的生命周期綁定,在onResume中獲取相機並預覽,在onPause中釋放相機資源,防止其他應用調用相機時出錯

private void releaseCamera() {
    if (mCamera != null) {
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

SurfaceHolder.Callback接口有create,change,destroy三個方法,我們在create中初始化,在change中預覽畫面,在destroy前釋放相機資源

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mCamera != null && mHolder != null) {
            setStartPreview(mCamera, mHolder);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mCamera != null) {
            mCamera.stopPreview();
            if (mHolder != null) {
                setStartPreview(mCamera, mHolder);
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }

最後就是點擊拍照並獲取圖片,這裡我們可以設置Camera.Parameters屬性作用於我們要拍攝的照片,調用tackPicture方法進行拍照

Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG); // 相片保存的格式
parameters.setPictureSize(800, 400); // 相片保存的尺寸,因為是橫屏所以長>高
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // 自動對焦
mCamera.autoFocus(new Camera.AutoFocusCallback() {
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        if (success) {
             // 拍照
             mCamera.takePicture(null, null, mPictureCallback);
         }
    }
});

takePicture的第一個參數是快門的回調,後面兩個都是圖像數據的回調,通常我們只需要實現第三個存儲照片的回調就可以了

private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        // 存儲的路徑及文件名
        mFilePath = mFilePath + "/" + System.currentTimeMillis() + ".png";
        File tempFile = new File(mFilePath);
        try {
            if (tempFile != null) {
                FileOutputStream fos = new FileOutputStream(tempFile);
                fos.write(data);
                fos.close();
                Intent intent = new Intent(CameraActivity.this, PictureActivity.class);
                 // 傳給下一個顯示照片的activity
                intent.putExtra("picPath", tempFile.getAbsolutePath());
                startActivity(intent);
                finish();
            }
        } catch (FileNotFoundException e) {
            Log.e(TAG, "onPictureTaken: " + e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, "onPictureTaken: " + e.getMessage() );
        }
    }
};

存儲完照片後,我們可以從傳遞的路徑獲取到圖片並顯示

mImageView = (ImageView) findViewById(R.id.iv_picture);
        mPath = getIntent().getStringExtra("picPath");
        try {
            FileInputStream fis = new FileInputStream(new File(mPath));
            Bitmap bitmap = BitmapFactory.decodeStream(fis);
            // 因為畫面預覽時是旋轉後顯示的,所以保存的圖片也需要旋轉90度
            Matrix matrix = new Matrix();
            matrix.setRotate(90);
            // 創建一個新的Bitmap
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            mImageView.setImageBitmap(bitmap);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "onCreate: FileInputStream error");
        }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved