My Android Camera Notes

來源:互聯網
上載者:User

 

1.
使用 SurfaceView
控制項來顯示相機擷取到的畫面

       <SurfaceView
android:layout_width="fill_parent"
android:layout_height="240dip"
android:id="@+id/surfaceView" />

 

2.
具體細節

       /*

擷取 SurfaceView

控制項 */

       SurfaceView
surfaceView = (SurfaceView)this.findViewById(R.id.surfaceView);

       /*

設定解析度 */

       surfaceView.getHolder().setFixedSize(176,
144);

       /*
下面設定Surface
不維護自己的緩衝區,而是等待螢幕的渲染引擎將內容推送到使用者面前*/

       surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

       /*

開啟網路攝影機,注意這裡是
android.hardware.Camera */

       Camera
camera = Camera.open();

      

       /*

為 Camera
設定攝像參數 */

       Camera.Parameters
parameters = camera.getParameters();

      

       /*

設定預覽照片的大小,此處設定為全屏 */

       WindowManager
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); //
擷取當前螢幕管理器對象

       Display
display = wm.getDefaultDisplay();                                      //
擷取螢幕資訊的描述類

       parameters.setPreviewSize(display.getWidth(),
display.getHeight());          //
設定

      

       /*

每秒從網路攝影機捕獲5
幀畫面, */

       parameters.setPreviewFrameRate(5);

       /*

設定照片的輸出格式:jpg
*/

       parameters.setPictureFormat(PixelFormat.JPEG);

       /*

照片品質 */

       parameters.set("jpeg-quality",
85);

       /*

設定照片的大小:此處照片大小等於螢幕大小 */

       parameters.setPictureSize(display.getWidth(),
display.getHeight());

       /*

將參數對象賦予到
camera
對象上 */

       camera.setParameters(parameters);

      

       /*

設定用
SurfaceView
作為承載鏡頭取景畫面的顯示
*/

       camera.setPreviewDisplay(surfaceView.getHolder());

       /*

開始預覽 */

       camera.startPreview();

       /*

自動對焦 */

       camera.autoFocus(null);

       /*

拍照片 */

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

       /*

停止預覽 */

       camera.stopPreview();

       /*

釋放網路攝影機 */

       camera.release();

 

3.
添加使用網路攝影機的許可權

       <uses-permission
android:name="android.permission.CAMERA"/>

 

4.
測試:
目前模擬器不支援拍照環境的類比,必須使用真實手機測試。

 

5.
代碼清單

    

**
string values : strings.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">手機拍照程式</string>
</resources>

 


**
AndroidManifest.xml

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="wjh.android.takepicture"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <!-- android:screenOrientation="landscape" 表示橫向介面 -->
        <activity android:name=".MainActicity" android:label="@string/app_name"  android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="8" />
    <!-- 在SDCard中建立與刪除檔案許可權 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 往SDCard寫入資料許可權 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 申請使用網路攝影機的許可權 -->
    <uses-permission android:name="android.permission.CAMERA"/>
</manifest>

 

   **
main.xml

 

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

 

 

**
MainActicity

 

public class MainActicity extends Activity {
    private Camera camera;
    private boolean preview  = false ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        /*
         *設定視窗屬性:一定要在 setContentView(R.layout.main) 之前
         */
        // 視窗標題
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 全屏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
       
        setContentView(R.layout.main);
       
       SurfaceView surfaceView =  (SurfaceView) findViewById(R.id.surfaceView);
       surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
       surfaceView.getHolder().setFixedSize(176, 164);
      
       surfaceView.getHolder().addCallback(new SurfaceViewCallback());
    }
   
    private final class SurfaceViewCallback implements Callback {
        /**
         * surfaceView 被建立成功後調用此方法
         */
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            /*
             * 在SurfaceView建立好之後 開啟網路攝影機
             * 注意是 android.hardware.Camera
             */
            camera = Camera.open();
            Camera.Parameters parameters = camera.getParameters();
            /* 設定預覽照片的大小,此處設定為全屏 */
            WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 擷取當前螢幕管理器對象
            Display display = wm.getDefaultDisplay();                           // 擷取螢幕資訊的描述類
            parameters.setPreviewSize(display.getWidth(), display.getHeight());          // 設定
           
            /* 每秒從網路攝影機捕獲5幀畫面, */
            parameters.setPreviewFrameRate(5);
            /* 設定照片的輸出格式:jpg */
            parameters.setPictureFormat(PixelFormat.JPEG);
            /* 照片品質 */
            parameters.set("jpeg-quality", 85);
            /* 設定照片的大小:此處照片大小等於螢幕大小 */
            parameters.setPictureSize(display.getWidth(), display.getHeight());
            /* 將參數對象賦予到 camera 對象上 */
            camera.setParameters(parameters);
            preview = true;
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
        }
        /**
         * SurfaceView 被銷毀時釋放掉 網路攝影機
         */
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if(camera != null) {
                /* 若網路攝影機正在工作,先停止它 */
                if(preview) {
                    camera.stopPreview();
                    preview = false;
                }       
                camera.release();
            }
        }
       
    }
   
   
    /**
     * 手機鍵盤按鍵事件
     * 返回 true, 將阻止事件繼續傳遞,例如搜尋鍵,他預設會觸發和開啟系統的搜尋引擎。返回true後,將不會觸發。
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        /*
         * event.getRepeatCount() 為重複按鍵的次數,例如,快速地對某個鍵連續按了兩次,則此值為一,表示重複了一次。往上可以累推。
         * 按鍵只被按了一次,則此值為 0。
         * 這有點類似於滑鼠的 "單擊" 和 "雙擊"。
         */
        if(camera != null && event.getRepeatCount() == 0 ) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_SEARCH: // 搜尋鍵
                /* 按下搜尋鍵自動對焦 , 如果要關注它的事件,
                 * 可以實現 AutoFocusCallback 介面,並執行個體化其對象傳入 */
                camera.autoFocus(null);
                break;
            case KeyEvent.KEYCODE_CAMERA: // 拍照鍵
            case KeyEvent.KEYCODE_DPAD_CENTER: // 中間確認鍵
                /*
                 * @param shutter : 照片被捕獲之後的回調對象
                 * @param raw : 此回調對象可以生產為壓縮的圖片資料
                 * @param jpeg : 此回調對象可以產生壓縮後的圖片資料,其onPictureTaken將被調用
                 */
                camera.takePicture(null, null, new TakePictureCallback());
               
                /* 拍完照後回到預覽狀態,繼續取景 -- 錯誤的方式 */
                // camera.startPreview();必須寫在 onPictureTaken 方法內部,因為 takePicture 內部是另開了一條線程非同步完成儲存照片等操作。
                // 雖然 takePicture 方法完成了,但是並不代表其內部的工作全部完成,也不代表網路攝影機以及從上一次“拍照”任務中工作完畢
                break;
            default:
                break;
            }
            return true;
        }
       
        return super.onKeyDown(keyCode, event);
    }
   
    /**
     * 處理照片被拍攝之後的事件
     */
    private final class TakePictureCallback implements PictureCallback {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
           
            /* 照片將被儲存到  SD 記憶卡跟目錄下,檔案名稱為系統時間,尾碼名為".jpg" */
            File file = new File(Environment.getExternalStorageState(), System.currentTimeMillis() + ".jpg");
            try {
                FileOutputStream fos = new FileOutputStream(file);
               
                /* 位元影像格式為JPEG
                 * 參數二位 0-100 的數值,100為最大值,表示無損壓縮
                 * 參數三傳入一個輸出資料流對象,將圖片資料輸出到流中
                 */
                bitmap.compress(CompressFormat.JPEG, 100, fos);
                fos.close();
               
                /* 拍完照後回到預覽狀態,繼續取景 */
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

轉自:

http://blog.csdn.net/wenlin56/archive/2010/12/16/6080984.aspx


作者:yiyaaixuexi 發表於2011-5-13 13:46:00 原文連結 閱讀:568 評論:1 查看評論

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.