1. 程式人生 > >android-Camera 崩潰分析

android-Camera 崩潰分析

ps:https://android.googlesource.com是google的git repositories on android可以下載需要的原始碼,需要翻牆進。

本文是對android攝像頭進行一些分析。在編譯的時候發現了錯誤,報出了w/CameraBase:An error occurred while connecting to camera:0 以及 W/System.error:java.lang.RuntimeException:Fail to connect to camera service;

(1)在java端掉用的程式碼如下:

private boolean safeCameraOpen(int id)

{

try{

ReleaseCamera();

        mCamera = Camera.open(id);

}catch(Exception e){

log.e("failed to open Camera"+e);

}

}

private void ReleaseCamera()

{ if(mCamera != null) { mCamera.release(); mCamera = null; } } 解決方案: (1)第一種可能是,因為在camera.open()之前沒有release調camera。( (2) 第二種可能是,攝像頭許可權的問題沒有加<uses-permission android:name="android.permission.CAMERA">
<uses-permission android:name="android.hardware.camera"> 以上兩種方法基本就可以解決掉在android原生開發下的報錯問題。但是如果是在跨平臺端來呼叫camera出錯就很難找到。 看下android下的camera.java原始碼,如下: public static Camera open(int cameraId){ return new Camera(cameraId); } //這裡的引數cameraId,是和初始化前置以及後置攝像頭有關的。0是前置攝像頭,1是後置攝像頭。還有另一個開啟攝像頭的介面,並不帶有引數,是預設開啟後置攝像頭的。如下所示。
public static Camera open() { int numberofCameras = getNumberOfCameras();//判斷攝像頭個數的,一般為2; CameraInfo cameraInfo = new CamearaInfo(); //一個攝像頭資訊的類 for(int i = 0;i<numberofCameras;i++) { getCameraInfo(i,cameraInfo); //預設開啟後置攝像頭 if(cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) return new Camera(i); } return null; } //這樣android的java層提供了兩種openCamera的方式。接下來是Camera的建構函式,如下: Camera(int cameraId) { int err = cameraInitNormal(cameraId);//這句是重點 if(checkInitErrors(err)){ //java.lang.RuntimeException: Fail to connect to camera service 就是這句報錯的地方 if(err == -EACCES){ throw new RuntimeException("Fail to connect to camera service"); }else if(err = -ENODEV) throw new RuntimeException("Camera Initialization failed"); } } //接著往下跟到cameraInitNormal(cameraId)這個接口裡面; private int cameraInitNormal(cameraId) { //cameraId就是當前的前置或後置攝像頭;CAMERA_HAL_API_VERSION_NORMAL_CONNECT這個應該當前版本camera的api。當跨平臺呼叫.jar包的時候,因為sdk版本的不同可能這裡會出現問題。                                                                                                                                                                                                                                    return cameraInitVersion(cameraId,CAMERA_HAL_API_VERSION_NORMAL_CONNECT); } private int cameraInitVersion(int cameraId,int halVersion) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; Looper looper; if((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this,looper); }else if((looper = Looper.getMainLooper()) != null) { mEventHandler = new EvenHandler(this,looper); }else{ mEventHandler =null; } //這裡將要呼叫到jni層的介面,它在camera.java中有宣告該native函式。 return native_setup(new WealReference<Camera>(this),cameraId,halVersion,ActivityThread.currentOpPackageName); } //宣告如下:private native final int native_setup(Object camera_this,int cameraIdmint halVersion,String packageName);在/framework/base/core/jni/android_hardware_Camera.cpp下可以找到對應介面: static jint android_hardware_Camera_native_setup(JNIEnv *env,jobject this,jobject weak_this,jint cameraId,jint halVersion,jstring clientPackageName) { //進行型別轉化;JNIEnv提供了大部分JNI功能。你定義的所有本地函式都會接收JNIEnv作為第一個引數。 const char16_t *rawClientName = reinterpret_cast<const char16_t*>(env->GetStringChars(clientPackageName,NULL)); size rawClientNameLen = env->GetStringLength(clientPackageName); String16 clientName(rawClientName,rawClientNameLen); env->ReleaseStringChars(clientPackageName,reinterpret_cast<const jchar*>(rawClientName)); sp<Camera> camera; if(halVersion = CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { camera = Camera::connect(cameraIdm,clientName,Ca,era::USE_CALLING_UID,Camera::USE_CALLING_PID); }