java-Android day07

Android Day04

by 木石溪
dev:1.0

本文要點:

  • 改進相機設計思路:
  1. 將上篇文章的調用系統相機軟件改爲自己設計相機;
  2. 增加相機的錄像功能(待定);

### 實現思路

  • 實現預覽
  • 實現授權

相機,文件讀取與存儲,麥克風權限;

  • 實現拍照
  • 相機資源釋放;

如此開始構建自己的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);
                }
            });

目前存在不足

  1. 相機啓動重新預覽失敗;
  2. 後面的任務是需要抓視屏時Frame數據;也是項目的關鍵

附上Demo:
Android Camera Demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章