2017-11-29 3 views
0

Mobile Vision API를 사용하여 전면 카메라의 얼굴을 감지합니다. Google의 FaceTracker 데모를 사용했지만 조각에서 사용해야합니다. 그것은 작동하지만, 화면을 회전하려고 할 때 예외 RuntimeException: Fail to connect to camera service와 응용 프로그램이 충돌합니다.화면 회전시 앱이 충돌합니다.

조각 코드 : 활동 코드에 따르면

class EyeTrackerFragment : Fragment(), AnkoLogger { 

private var cameraSource: CameraSource? = null 

private lateinit var cameraSourcePreview: CameraSourcePreview 
private lateinit var graphicOverlay: GraphicOverlay 

private var callback: OnEyeContextUpdatedListener? = null 

companion object { 
    // google play services error code 
    private val RC_HANDLE_GMS = 9001 
    // permission request codes need to be < 256 
    private val RC_HANDLE_CAMERA_PERM = 2 
} 

override fun onAttach(context: Context?) { 
    super.onAttach(context) 

    try { 
     callback = activity as OnEyeContextUpdatedListener 
    } catch (e: ClassCastException) { 
     throw ClassCastException("${activity} must implement OnEyeContextUpdatedListener") 
    } 
} 

/** 
* Restarts the camera. 
*/ 
override fun onResume() { 
    super.onResume() 

    startCameraSource() 
} 

/** 
* Stops the camera. 
*/ 
override fun onPause() { 
    super.onPause() 
    cameraSourcePreview.stop() 
} 

/** 
* Releases the resources associated with the camera source, the associated detector, and the 
* rest of the processing pipeline. 
*/ 
override fun onDestroy() { 
    super.onDestroy() 
    cameraSource?.release() 
} 

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? = 
     inflater!!.inflate(R.layout.fragment_face_tracker, container, false) 

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { 
    super.onViewCreated(view, savedInstanceState) 

    cameraSourcePreview = getView()!!.findViewById<View>(R.id.preview) as CameraSourcePreview 
    graphicOverlay = getView()!!.findViewById<View>(R.id.faceOverlay) as GraphicOverlay 

    if (ActivityCompat.checkSelfPermission(context.applicationContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { 
     createCameraSource() 
    } else { 
     requestCameraPermission() 
    } 
} 

/** 
* Handles the requesting of the camera permission. This includes 
* showing a "Toast" message of why the permission is needed then 
* sending the request. 
*/ 
private fun requestCameraPermission() { 
    warn("Camera permission is not granted. Requesting permission") 

    val permissions = arrayOf(Manifest.permission.CAMERA) 

    if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, 
      Manifest.permission.CAMERA)) { 
     ActivityCompat.requestPermissions(activity, permissions, RC_HANDLE_CAMERA_PERM) 
     return 
    } 

    Toast.makeText(context.applicationContext, "Give me permissions", Toast.LENGTH_LONG).show() 
} 

private fun createCameraSource() { 
    val detector = FaceDetector.Builder(context.applicationContext) 
      .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS) 
      .setProminentFaceOnly(true) 
      .setTrackingEnabled(true) 
      .setMode(FaceDetector.ACCURATE_MODE) 
      .build() 

    val faceTracker = GraphicFaceTracker(graphicOverlay, callback, context) 
    val faceProcessor = LargestFaceFocusingProcessor(detector, faceTracker) 
    detector.setProcessor(faceProcessor) 

    if (!detector.isOperational) { 
     longToast("Face detector dependencies are not yet available.") 
    } 

    cameraSource = CameraSource.Builder(context, detector) 
      .setRequestedPreviewSize(640, 480) 
      .setFacing(CameraSource.CAMERA_FACING_FRONT) 
      .setRequestedFps(30.0f) 
      .build() 
} 

private fun startCameraSource() { 
    // check that the device has play services available. 
    val code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
      context.applicationContext) 
    if (code != ConnectionResult.SUCCESS) { 
     val dlg = GoogleApiAvailability.getInstance().getErrorDialog(activity, code, RC_HANDLE_GMS) 
     dlg.show() 
    } 

    if (cameraSource != null) { 
     try { 
      cameraSourcePreview.start(cameraSource!!, graphicOverlay) 
     } catch (e: IOException) { 
      error("Unable to start camera source.", e) 
      cameraSource!!.release() 
      cameraSource = null 
     } 

    } 
} 

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { 
    if (requestCode != RC_HANDLE_CAMERA_PERM) { 
     debug("Got unexpected permission result: $requestCode") 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults) 
     return 
    } 

    if (grantResults.size != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
     debug("Camera permission granted - initialize the camera source") 
     createCameraSource() 
     return 
    } 

    error("Permission not granted: results len = ${grantResults.size}. Result code = ${if (grantResults.isNotEmpty()) grantResults[0] else "(empty)"}") 

    val builder = AlertDialog.Builder(context) 
    builder.setTitle("Face Tracker sample") 
      .setMessage("Have no camera permission") 
      .setPositiveButton("Ok", { _, _ -> activity.finish() }) 
      .show() 
} 

}

. onCreate 메서드에서 이전 단편을 부착 한 다음 아무 것도하지 않습니다.

카메라 인스턴스가 일부 상황에서는 해제되지 않았지만 Activity와 같은 방식으로 처리됩니다. Fragment에 액티비티와 비교하여 추가 동작이 필요한 특수 동작이 있습니까?

전체 예외 로그 : 안드로이드 파괴와 방향의 변화를위한 활동을 재현 할 때마다

E/AndroidRuntime: FATAL EXCEPTION: main 
       Process: com.eyetracker.android.demo, PID: 22631 
       java.lang.RuntimeException: Fail to connect to camera service 
        at android.hardware.Camera.<init>(Camera.java:520) 
        at android.hardware.Camera.open(Camera.java:361) 
        at com.google.android.gms.vision.CameraSource.zzchq(Unknown Source) 
        at com.google.android.gms.vision.CameraSource.start(Unknown Source) 
        at com.eyetracker.android.camera.CameraSourcePreview.startIfReady(CameraSourcePreview.kt:82) 
        at com.eyetracker.android.camera.CameraSourcePreview.access$startIfReady(CameraSourcePreview.kt:18) 
        at com.eyetracker.android.camera.CameraSourcePreview$SurfaceCallback.surfaceCreated(CameraSourcePreview.kt:104) 
        at android.view.SurfaceView.updateWindow(SurfaceView.java:580) 
        at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:176) 
        at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:948) 
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1974) 
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1065) 
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5901) 
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
        at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
        at android.view.Choreographer.doFrame(Choreographer.java:550) 
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:211) 
        at android.app.ActivityThread.main(ActivityThread.java:5389) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815) 
+0

코드 및 오류 로그를 추가하십시오 – kimkevin

+0

android : configChanges = "orientation | keyboardHidden"을 사용해 보셨습니까? – Bek

+0

그게 어떻게 도움이 되었습니까? –

답변

0

, 그것은 onSaveInstanceState()를 호출합니다.

따라서 onSaveInstanceState()의 번들에 필요한 데이터를 저장하고 savedInstanceState 필드가 null인지 확인하여 onCreate()에 복원하십시오.

관련 문제