Android Day04
by 木石溪
dev:1.0
本文要點:
- 改進相機設計思路:
- 將上篇文章的調用系統相機軟件改爲自己設計相機;
- 增加相機的錄像功能(待定);
### 實現思路
- 實現預覽
- 實現授權
相機,文件讀取與存儲,麥克風權限;
- 實現拍照
- 相機資源釋放;
如此開始構建自己的80年代相機吧!
Step 01. 添加權限
爲了使用相機硬件以及照片存儲功能,首先讓我們添加權限
/* Before developing our camera application with camera API, we need get the permission to allow use of camera hardware and other related features. */ // At least, you need add the flowing sentence to your **AndroidManifest.xml** <uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.hardware.camera.autofocus"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Step 02. 設計相機界面
主要包括一個 FrameView 和一個 Button
/* in this project, we need a frameview for a camera preview and a button for take a picture */ // adding the flowing sentence to the activity_main.xml <FrameLayout android:id="@+id/camera_preview" android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="@string/bt_capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" />
Step 03. 檢測並獲取相機
檢測相機是否存在
/* *aim: 1. detect and access the camera --- the code creating for checking the extension of camera and requesting the access */ // detect the extension of the camera private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { return true; } else { Toast.makeText(MainActivity.this, "NO CAMERA", Toast.LENGTH_SHORT).show(); return false; } } // request the access of camera public static Camera getCameraInstance() { Camera c = null; try { c= Camera.open(); } catch (Exception e) { Log.d(TAG, "camera is not available: " + e.getMessage()); } return c; }
Step 04. 實現相機預覽功能
實現相機的預覽框功能
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; mHolder = getHolder(); mHolder.addCallback(this); // mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // 當Surface被創建之後,開始Camera的預覽 try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting a camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mHolder.getSurface() == null) { return; } // 停止Camera的預覽 try { mCamera.stopPreview(); } catch (Exception e) { Log.d(TAG, "Try to stop a non-existent preview" + e.getMessage()); } // 重新開始預覽 try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d(TAG, "Error restarting camera preview: " + e.getMessage()); } } }
Step 05. 實現相機拍照功能
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // Creating a new file path to saving a picture File pictureFile = new File("/sdcard/" + System.currentTimeMillis() + ".jpg"); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions"); return; } // start taking a picture try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (Exception e) { Log.d(TAG, "Error save the picture: " + e.getMessage()); } } };
Step 07. 相機資源釋放
相機資源釋放,避免內存報錯
@Override protected void onDestroy() { // 回收Camera資源 if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } super.onDestroy(); }
Step 08. 模塊組裝
到這爲止,相機主要功能已經實現了,接下來我們就是在 onCreate()函數中添加相機和文件權限以及實現相機組裝
// check the permission of camera and storage, request the permission if don't have if (Build.VERSION.SDK_INT >= 23) { String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; if (MainActivity.this.checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED || MainActivity.this.checkSelfPermission(permissions[1]) != PackageManager.PERMISSION_GRANTED || MainActivity.this.checkSelfPermission(permissions[2]) != PackageManager.PERMISSION_GRANTED) { //申請權限 MainActivity.this.requestPermissions(permissions, PERMISSION_REQUEST_CODE_STORAGE_WRITE); MainActivity.this.requestPermissions(permissions, PERMISSION_REQUEST_CODE_STORAGE_READ); MainActivity.this.requestPermissions(permissions, PERMISSION_REQUEST_CODE_CAMERA); } } // stat the camera preview mCamera = getCameraInstance(); mPreview = new CameraPreview(this, mCamera); FrameLayout preview = findViewById(R.id.camera_preview); preview.addView(mPreview); // start the button listener and take a picture Button bt_capture = findViewById(R.id.button_capture); bt_capture.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCamera.takePicture(null, null, mPicture); } });
目前存在不足
- 相機啓動重新預覽失敗;
- 後面的任務是需要抓視屏時Frame數據;也是項目的關鍵
附上Demo:
Android Camera Demo