Android Studio 呼叫Camera實現拍照功能
最近總想寫寫,但又不知寫些什麼,想了想,今天寫個Camera拍照的教程吧。本例子的流程為 首先通過SurfaceView將Camera的實時畫面顯示在螢幕上,然後通過點選拍照對當前畫面進行捕捉,最後將獲得的圖片儲存至本地。
- 首先建立一個SurfaceHolder實現對SurfaceView的回撥,然後重寫SurfaceCreate函式,實現對Camera的初始化等一系列工作:程式碼如下:
@Override public void surfaceCreated(SurfaceHolder holder) { Log.e("TAG","------surfaceCreated------"); try { //這裡我優先找後置攝像頭,找不到再找前面的 int cameraIndex = findBackOrFrontCamera(Camera.CameraInfo.CAMERA_FACING_BACK); if (cameraIndex == -1) { cameraIndex = findBackOrFrontCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); if (cameraIndex == -1) { Log.e("TAG", "No Camera!"); currentCameraType = CAMERA_NOTEXIST; currentCameraIndex = -1; return; } else { currentCameraType = FRONT; } } else { currentCameraType = BACK; } //找到想要的攝像頭後,就開啟 if (mCamera == null) { mCamera = openCamera(currentCameraType); } } catch (Exception e) { e.printStackTrace(); } }
本例子中,我首先找到想要開啟的攝像頭,這裡的優先尋找後置攝像頭,如果沒有找到,再找前置的,程式碼如下:
/** * 按要求查詢攝像頭 * * @param camera_facing 按要求查詢,鏡頭是前還是後 * @return -1表示找不到 */ private int findBackOrFrontCamera(int camera_facing) { int cameraCount = 0; Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); cameraCount = Camera.getNumberOfCameras(); for (int camIdx = 0; camIdx < cameraCount; camIdx++) { Camera.getCameraInfo(camIdx, cameraInfo); if (cameraInfo.facing == camera_facing) { return camIdx; } } return -1; }
當找到攝像頭後,便開啟Camera,其實開啟Camera可以直接用open(CameraId)函式即可,但我在重新封裝了一下,直接帖程式碼:
/** * 按照type的型別開啟相應的攝像頭 * * @param type 標誌當前開啟前還是後的攝像頭 * @return 返回當前開啟攝像機的物件 */ private Camera openCamera(int type) { int frontIndex = -1; int backIndex = -1; int cameraCount = Camera.getNumberOfCameras(); Camera.CameraInfo info = new Camera.CameraInfo(); for (int cameraIndex = 0; cameraIndex < cameraCount; cameraIndex++) { Camera.getCameraInfo(cameraIndex, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { frontIndex = cameraIndex; } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { backIndex = cameraIndex; } } currentCameraType = type; if (type == FRONT && frontIndex != -1) { currentCameraIndex = frontIndex; return Camera.open(frontIndex); } else if (type == BACK && backIndex != -1) { currentCameraIndex = backIndex; return Camera.open(backIndex); } return null; }
- 然後在SurfaceChange對Camera進行一系列初始化(對攝像頭初始化,就是設定圖片格式,圖片尺寸等賦值,要開啟攝像頭才可以初始化,否則會報錯)
/** * 初始化攝像頭 * @param holder */ private void initCamera(SurfaceHolder holder){ Log.e("TAG","initCamera"); if (mPreviewRunning) mCamera.stopPreview(); Camera.Parameters parameters; try{ //獲取預覽的各種解析度 parameters = mCamera.getParameters(); }catch (Exception e){ e.printStackTrace(); return; } //這裡我設為480*800的尺寸 parameters.setPreviewSize(480,800); // 設定照片格式 parameters.setPictureFormat(PixelFormat.JPEG); //設定圖片預覽的格式 parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); setCameraDisplayOrientation(this,currentCameraIndex,mCamera); try{ mCamera.setPreviewDisplay(holder); }catch(Exception e){ if(mCamera != null){ mCamera.release(); mCamera = null; } e.printStackTrace(); } mCamera.startPreview(); mPreviewRunning = true; } /** * 設定旋轉角度 * @param activity * @param cameraId * @param camera */ private void setCameraDisplayOrientation(Activity activity,int cameraId,Camera camera){ Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId,info); int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch(rotation){ case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){ result = (info.orientation + degrees) % 360; result = (360 - result) % 360; }else{ result = (info.orientation - degrees +360) % 360; } camera.setDisplayOrientation(result); }
- 當這些工作完成後,便可以對當前攝像頭捕捉的畫面進行拍照了:
/** * 實現拍照功能 */ public void takePhoto(){ Camera.Parameters parameters; try{ parameters = mCamera.getParameters(); }catch(Exception e){ e.printStackTrace(); return; } //獲取攝像頭支援的各種解析度,因為攝像頭陣列不確定是按降序還是升序,這裡的邏輯有時不是很好找得到相應的尺寸 //可先確定是按升還是降序排列,再進對對比吧,我這裡攏統地找了個,是個不精確的... List<Camera.Size> list = parameters.getSupportedPictureSizes(); int size = 0; for (int i =0 ;i < list.size() - 1;i++){ if (list.get(i).width >= 480){ //完美匹配 size = i; break; } else{ //找不到就找個最接近的吧 size = i; } } //設定照片解析度,注意要在攝像頭支援的範圍內選擇 parameters.setPictureSize(list.get(size).width,list.get(size).height); //設定照相機引數 mCamera.setParameters(parameters); //使用takePicture()方法完成拍照 mCamera.autoFocus(new Camera.AutoFocusCallback() { //自動聚焦完成後拍照 @Override public void onAutoFocus(boolean success, Camera camera) { if (success && camera != null){ mCamera.takePicture(new ShutterCallback(), null, new Camera.PictureCallback() { //拍照回撥介面 @Override public void onPictureTaken(byte[] data, Camera camera) { savePhoto(data); //停止預覽 mCamera.stopPreview(); //重啟預覽 mCamera.startPreview(); } }); } } }); } /* *//** * 快門回撥介面,如果不想拍照聲音,直接將new ShutterCallback()修改為null即可 */ private class ShutterCallback implements Camera.ShutterCallback { @Override public void onShutter() { MediaPlayer mPlayer = new MediaPlayer(); mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.shutter); try{ mPlayer.prepare(); }catch (IllegalStateException e){ e.printStackTrace(); }catch (IOException e){ e.printStackTrace(); } mPlayer.start(); } }
這裡要注意下,有些手機呼叫onAutoFocus函式,會返回失敗,因為如果該手機無自動對焦,則無法執行對焦成功後的函式了。。。
-
當捕捉到資料後,便可以將這些資料儲存至設定的地方了:
/** * 設定照片的路徑,具體路徑可自定義 * @return */ private String setPicSaveFile(){ //建立儲存的路徑 File storageDir = getOwnCacheDirectory(this,"MyCamera/photos"); //返回自定義的路徑 return storageDir.getPath(); } private File getOwnCacheDirectory(Context context, String cacheDir) { File appCacheDir = null; //判斷SD卡正常掛載並且擁有根限的時候建立檔案 if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)){ appCacheDir = new File(Environment.getExternalStorageDirectory(),cacheDir); } if (appCacheDir == null || !appCacheDir.exists() && !appCacheDir.mkdirs()){ appCacheDir = context.getCacheDir(); } return appCacheDir; } /** * 檢查是否有許可權 * @param context * @return */ private boolean hasExternalStoragePermission(Context context) { int permission = context.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE"); //PERMISSION_GRANTED=0 return permission == 0; }
由於呼叫了系統Camera和對SD卡讀寫,所以在AndroidManifest需要申請許可權:
<!--攝像頭相關許可權--> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 在SDCard中建立與刪除檔案許可權 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard寫入資料許可權 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
後記:google在Android5.0後推出了Camera的升級版---Camera2:
按照Android的官方說明,camera 2支援以下5點新特性,有興趣的可以研究下:
(1)支援每秒30幀的全高清連拍。
(2)支援在每幀之間使用不同的設定。
(3)支援原生格式的影像輸出。
(4)支援零延遲快門和電影速拍。
(5)支援相機在其他方面的手動控制,比如設定噪音消除的級別。
最後也貼出本例子的原始碼吧,有興趣的可以到Github上下載本例子;如果支援本文,也可以直接在CSDN本站上下載github的連結地址:CSDN地址:https://download.csdn.net/download/toyauko/10636251
相關文章
- Android Camera——拍照Android
- Android 呼叫攝像頭功能【拍照與視訊】Android
- 使用Webcam實現拍照功能Web
- 純JavaScript實現的呼叫裝置攝像頭並拍照的功能JavaScript
- C#實現攝像頭呼叫、拍照C#
- Android自定義拍照實現Android
- android實現拍照、相簿選圖、裁剪功能,相容7.0以及小米Android
- Android呼叫攝像頭拍照Android
- Android 呼叫攝像頭拍照Android
- Android:呼叫系統相機實現拍照+裁切(相容7.0以上系統)Android
- html5呼叫攝像頭實現拍照HTML
- android studio呼叫攝像頭拍照及具體步驟演示程式碼Android
- Android 呼叫相簿 拍照 實現系統控制元件縮放 切割圖片Android控制元件
- Android camera2實現預覽Android
- android 實現拍照的2種方法Android
- Android 高仿微信 獲取最近剛剛拍照的縮圖 功能實現Android
- 通過HTML5的getUserMedia實現拍照功能HTML
- 照片系列之android呼叫攝像頭拍照Android
- Android開發之呼叫攝像頭拍照Android
- Android呼叫系統相簿和相機拍照Android
- Android呼叫攝像頭拍照並顯示照片Android
- 【Android】【opencv】實現攝像頭拍照和錄影AndroidOpenCV
- Android Studio實現程式碼混淆Android
- Android 呼叫系統相機拍照 . 選取本地相簿Android
- asp.net WebService實現跨域js呼叫功能實現ASP.NETWeb跨域JS
- Android Traceroute 功能實現Android
- android截圖功能實現Android
- Android:CameraAndroid
- Android Camera 系列(二)控制CameraAndroid
- android studio模版功能簡介Android
- Android Studio 2.0 功能介紹Android
- 安卓呼叫PrinterShare實現無線列印功能安卓
- js如何實現手機呼叫震動功能JS
- Music Studio專案心得--JNI實現C++呼叫JAVAC++Java
- 使用 Camera2 API 實現 Android 手電筒應用APIAndroid
- android 拍照Android
- Android拍照Android
- Android 呼叫已安裝市場,進行軟體評分的功能實現Android