控制摄像头拍照
現在的智能手機和平板電腦一般都會提供攝像頭拍照功能。在Android中提供了專門用于處理攝像頭相關事件的類,即android.hardware包中的Camera類。Camera類沒有構造方法,可以通過其提供的open()方法打開攝像頭。打開攝像頭后,可以通過Camera.Parameters類處理攝像頭的拍照參數。拍照參數設置完成后,可以調用startPreview()方法預覽拍照畫面,也可以調用takePicture()方法進行拍照。結束程序時,可以調用Camera類的stopPreview()方法結束預覽,并調用release()方法釋放攝像頭資源。Camera類常用的方法如表10.9所示。
表10.9 Camera類常用的方法
下面通過一個實例來說明控制攝像頭拍照的具體過程。
實例 實現控制攝像頭拍照功能
在Android Studio中創建Module,名稱為“Camera”,在該Module中實現本實例,具體步驟如下。
(1)修改布局文件activity_main.xml,首先將默認添加的布局管理器修改為幀布局管理器,然后將TextView組件刪除,再添加一個SurfaceView組件(用于顯示攝像頭預覽畫面),最后添加一個預覽按鈕和一個拍照按鈕。具體代碼請參見光盤。
(2)打開MainActivity類,該類繼承Activity,然后在該類中,定義所需的成員變量,關鍵代碼如下:
01 private Camera camera; //定義相機對象 02 private boolean isPreview = false; //定義非預覽狀態
(3)在MainActivity類的onCreate()方法中,首先設置全屏顯示,然后判斷手機是否安裝SD卡,關鍵代碼如下:
01 //設置全屏顯示
02 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
03 WindowManager.LayoutParams.FLAG_FULLSCREEN);
04 if (!Environment.getExternalStorageState().equals( //判斷手機是否安裝SD卡
05 Environment.MEDIA_MOUNTED)) {
06 Toast.makeText(this, "請安裝SD卡!", Toast.LENGTH_SHORT).show(); // 提示安裝SD卡
07 }
(4)獲取SurfaceView組件與SurfaceHolder對象,用于顯示攝像頭預覽,關鍵代碼如下:
01 //獲取SurfaceView組件,用于顯示攝像頭預覽 02 SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView); 03 final SurfaceHolder sh = sv.getHolder(); //獲取SurfaceHolder對象 04 //設置該SurfaceHolder自己不維護緩沖 05 sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 06 ImageButton preview = (ImageButton) findViewById(R.id.preview); //獲取“預覽”按鈕 07 ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto); //獲取“拍照”按鈕
(5)為預覽按鈕添加單擊事件監聽器,實現攝像頭的預覽功能,關鍵代碼如下:
01 preview.setOnClickListener(new View.OnClickListener() { //實現攝像頭預覽功能
02 @Override
03 public void onClick(View v) {
04 // 如果攝像頭為非預覽模式,則打開相機
05 if (!isPreview) {
06 camera = Camera.open(); /打開相機
07 isPreview = true; //設置為預覽狀態
08 }
09 try {
10 camera.setPreviewDisplay(sh); //設置用于顯示預覽的SurfaceView
11 Camera.Parameters parameters = camera.getParameters(); //獲取相機參數
12 parameters.setPictureFormat(PixelFormat.JPEG); //指定圖片為JPEG圖片
13 parameters.set("jpeg-quality", 80); //設置圖片的質量
14 camera.setParameters(parameters); //重新設置相機參數
15 camera.startPreview(); //開始預覽
16 camera.autoFocus(null); //設置自動對焦
17 } catch (IOException e) { //輸出異常信息
18 e.printStackTrace();
19 }
20 }
21 });
(6)在MainActivity中,創建實現重新預覽的方法resetCamera(),在該方法中,當isPreview變量的值為真時,調用攝像頭的startPreview()方法開啟預覽,具體代碼如下:
01 private void resetCamera() { //創建resetCamera()方法,實現重新預覽功能
02 if (!isPreview) { //如果為非預覽模式
03 camera.startPreview(); //開啟預覽
04 isPreview = true;
05 }
06 }
(8)實現拍照的回調接口,在重寫的onPictureTaken()方法中,首先根據拍照所得的數據創建位圖,然后保存所拍攝的圖片,再把保存的圖片文件插入到系統圖庫,最后通知圖庫更新,具體代碼如下:
01
02 //實現將照片保存到系統圖庫中
03 final Camera.PictureCallback jpeg = new Camera.PictureCallback() { //照片回調函數
04 @Override
05 public void onPictureTaken(byte[] data, Camera camera) {
06 // 根據拍照所得的數據創建位圖
07 final Bitmap bm = BitmapFactory.decodeByteArray(data, 0,
08 data.length);
09 camera.stopPreview(); //停止預覽
10 isPreview = false; //設置為非預覽狀態
11 //獲取sd卡根目錄
12 File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/");
13 if (!appDir.exists()) { //如果該目錄不存在
14 appDir.mkdir(); //創建該目錄
15 }
16 //將獲取的當前系統時間設置為照片名稱
17 String fileName = System.currentTimeMillis() + ".jpg";
18 File file = new File(appDir, fileName); //創建文件對象
19 try { //保存拍到的圖片
20 FileOutputStream fos = new FileOutputStream(file); //創建一個文件輸出流對象
21 //將圖片內容壓縮為JPEG格式輸出到輸出流對象中
22 bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
23 //將緩沖區中的數據全部寫出到輸出流中
24 fos.flush();
25 fos.close(); //關閉文件輸出流對象
26 } catch (FileNotFoundException e) {
27 e.printStackTrace();
28 } catch (IOException e) {
29 e.printStackTrace();
30 }
31 //將照片插入到系統圖庫
32 try {
33 MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),
34 file.getAbsolutePath(), fileName, null);
35 } catch (FileNotFoundException e) {
36 e.printStackTrace();
37 }
38 //最后通知圖庫更新
39 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
40 Uri uri = Uri.fromFile(file);
41 intent.setData(uri);
42 MainActivity.this.sendBroadcast(intent); //這個廣播的目的就是更新圖庫
43 Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show();
44 resetCamera(); //調用重新預覽resetCamera()方法
45 }
46 };
(9)在onCreate()方法中,為拍照按鈕添加單擊事件監聽器,實現攝像頭的拍照功能,關鍵代碼如下:
01 takePicture.setOnClickListener(new View.OnClickListener() {
02 @Override
03 public void onClick(View v) {
04 if (camera != null) { //相機不為空
05 camera.takePicture(null, null, jpeg); //進行拍照
06 }
07 }
08 });
(10)重寫Activity的onPause()方法,用于當暫停Activity時,停止預覽并釋放攝像頭資源,具體代碼如下:
01 @Override
02 protected void onPause() {
03 if (camera != null) { //如果攝像頭不為空
04 camera.stopPreview(); //停止預覽
05 camera.release(); //釋放資源
06 }
07 super.onPause();
08 }
(11)由于本程序需要訪問SD卡和控制攝像頭,所以需要在AndroidManifest.xml文件中賦予程序訪問SD卡和控制攝像頭的權限,關鍵代碼如下:
01 <!-- 授予程序可以向SD卡中保存文件的權限 --> 02 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 03 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 04 <!-- 授予程序使用攝像頭的權限 --> 05 <uses-permission android:name="android.permission.CAMERA"/> 06 <uses-feature android:name="android.hardware.camera.autofocus"/> 07 <uses-feature android:name="android.hardware.camera"/>
(12)在AndroidManifest.xml文件的<activity>標記中添加screenOrientation屬性,設置其橫屏顯示,關鍵代碼如下:
android:screenOrientation="landscape"
(13)在工具欄中找到下拉列表框,選擇要運行的應用(這里為Camera),再單擊右側的按鈕,在顯示的界面中,單擊預覽按鈕,啟動攝像頭,單擊拍照按鈕進行拍照,如圖10.9所示。
圖10.9 預覽與拍照
說明:本實例需要攝像頭硬件的支持,這里我們使用真機測試。讀者需要在手機中手動開啟攝像頭權限與sd卡讀寫權限。
本文來自明日科技出版的《零基礎學Android》,轉載請注明出處!??!
總結
- 上一篇: 浙江移动营业厅APP
- 下一篇: 小技巧:通过“Apple 支持”应用更改