Camera와 OpenGL 동시에 표시하기

  안드로이드에서 카메라와 OpenGL을 동시에 표시하는 

  것을 구현하려고 했더니 잘안되어서 검색을 좀 해봤습니다. 

  해당 이슈는 이미 Google groups 에서 논의되었었는데

  
  제목으로 검색하시면 찾을 수 있습니다.

  제가 처음 시도한 것처럼 카메라 Preview 를 먼저 보이게 하고

  투명한 배경의 OpenGL 화면을 보이게 하려고 했는데

  카메라만 보인다는 내용입니다.

  저역시 카메라만 보이는 것을 확인할 수 있었는데,

  Julius 라는 사람이 쓴 답글을 보면 순서를 거꾸로 하여

  OpenGL을 먼저하고 나중에 카메라를 더하라는 것이 있었습니다.

  그렇게 해보니 신기하게도 카메라 영상과 OpenGL 이 겹쳐져 나오더군요.

  <<디바이스 실행화면>>



  아래의 코드대로 해보시면 아시겠지만, 1.5 버전의 에뮬레이터에서

  투명한 배경이 동작하지 않는 것을 확인했습니다. 

  제가 설치한 에뮬레이터의 버전 문제일지 모르겠으나, 투명이 아니라 

  백색화면에 그래픽 객체는 나오지 않더군요. 

  또다른 구글그룹스의 내용에는 멀티 SurfaceView 를 권장하지 않는다고

  안드로이드 프레임웍 엔지니어가 답글을 달았군요.

  코드는 Cube.java 와 CubeRenderer.java 를 참조하고 있습니다.

  public class camGL extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        requestWindowFeature(Window.FEATURE_NO_TITLE);

        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        

        Preview mPreview = new Preview(this); 

        

        mRenderer = new CubeRenderer(true);

        

        mGLSurfaceView = new GLSurfaceView(this);

        //translucent

        mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

        mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);

        mGLSurfaceView.setRenderer(mRenderer);

        

     //OpenGL 먼저 표시하기

        setContentView(mGLSurfaceView); 

     //그 다음 카메라 표시하기

        addContentView(mPreview, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        

    }

    

    private GLSurfaceView mGLSurfaceView;

    private CubeRenderer mRenderer;


    @Override

    protected void onResume() {

        super.onResume();

        

    }


    @Override

    protected void onPause() {

        super.onPause();

        

    }

    

}

//////////////////////////////

// camer preview

////////////////////////////

class Preview extends SurfaceView implements SurfaceHolder.Callback { 

    SurfaceHolder mHolder

    Camera mCamera

    

    boolean mPreviewRunning = false;

    

    Preview(Context context) { 

        super(context); 

        mHolder = getHolder(); 

        mHolder.addCallback(this); 

        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

        

    } 


    Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {

        public void onPictureTaken(byte[] data, Camera c) {

            mCamera.startPreview();

        }

    };

    

    public void surfaceCreated(SurfaceHolder holder) { 

        mCamera = Camera.open(); 

        try{

        mCamera.setPreviewDisplay(holder);

         if (false) throw new IOException(); 

        }catch (IOException e){

        //do something

        }

    } 


    public void surfaceDestroyed(SurfaceHolder holder) { 

        mCamera.stopPreview();

        mPreviewRunning = false;//// added

        mCamera = null

    } 


    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 

     if (mPreviewRunning) {    ///added

            mCamera.stopPreview();

        }

    

        Camera.Parameters parameters = mCamera.getParameters(); 

        parameters.setPreviewSize(w, h); 

        mCamera.setParameters(parameters);

        mCamera.startPreview(); 

        //

        try{

        mCamera.setPreviewDisplay(holder);

         if (false) throw new IOException(); 

        }catch (IOException e){

        //do something

        }

        mCamera.startPreview();

        mPreviewRunning = true///added

    } 


}


  ANDROID 1.5 R3 업데이트

  안드로이드 1.5 release 3가 업데이트 되었네요.

  G1 폰에도 갑자기 업데이트가 되었답니다.

  그런데, 주로 카메라 관련 어플을 만들고 있던 저로서는 

  당황스런 일이 발생했답니다.

  에러가 전혀 없는데도 불구하고 더이상 예기치 못한 오류로

  동작이 안되는 겁니다. 기존의 카메라는 잘 동작하는데

  이상하게 안되어서 에뮬레이터를 확인해 보니 정상동작하는 게 아니겠습니까...

  업데이트로 인해 정상동작이 안되는 것이었지요.

  G1폰이 문제인줄 알고선, 다운그레이드 하고 호들갑을 떨었는데,

  SDK가 업데이트 된 것을 나중에 알고 업데이트 해보니 에뮬레이터도 마찬가지의 오류가 발생하더군요.

  


카메라 오류

  그래서 어쨌던지 문제를 해결해야 했기 때문에 알아보니 이번 릴리즈 3에서는

  카메라를 동작시키려면 permission 을 강제적으로 확인한다는 군요.

When an application requests access to device camera (through android.hardware.camera), the CAMERA permission check is now properly enforced.

  그런데 아래와 같이 이미 적용되어 있었는데, 계속 오류가 나서 이상하다 했답니다.

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


  그런데 확인해 보니 위치가 잘못되어 오동작 했던 거였답니다.

  그리고 이전에는 체크가 안되고 있어서 위치가 잘못되었는지 몰랐던 거죠.

  초심으로 돌아가서 정리하는 차원으로 Manifest file의 각 구문 위치를 정리합니다.

  괜한 삽질로 하루만 날렸군요. 게다가 1.5로 다시 업데이트 해야 하는데, 언제 자동으로 

  될런지 기다려야 할지 아니면 강제로 업데이트 해야 할지 고민됩니다.

  <?xml version="1.0" encoding="utf-8"?>
<manifest>

    <uses-permission />
    <permission />
    <permission-tree />
    <permission-group />

    <instrumentation />

    <uses-sdk />

    <application>

        <activity>
            <intent-filter>
                <action />
                <category />
                <data />
            </intent-filter>
            <meta-data />
        </activity>

        <activity-alias>
            <intent-filter> . . . </intent-filter>
            <meta-data />
        </activity-alias>

        <service>
            <intent-filter> . . . </intent-filter>
            <meta-data/>
        </service>

        <receiver>
            <intent-filter> . . . </intent-filter>
            <meta-data />
        </receiver>

        <provider>
            <grant-uri-permission />
            <meta-data />
        </provider>

        <uses-library />
        <uses-configuration />  

    </application>

</manifest>

  카메라 Landscape 로 실행하기

  이전 포스팅에서 카메라를 실행해서 Preview 함수로

  영상을 보면 키보드를 열지 않은 상태에서는

  90도로 회전된 영상이 보였었다. 

  일부에서는 버그라고 취급하고 있었는데


  기본으로 제공되는 카메라나 캠코더, Wikitude 등의 

  APP에서는 Portrait mode 에서도 정상적으로 

  카메랑 영상이 나오는 것을 알수 있다. 

  오랜 검색 끝에 해결방법을 알아냈다.

  방법은 designerandroid.com에서 발견하였고,

  APP의 Activity 가 처음 실행되는 곳인 onCreate 함수에 다음의 문장을 삽입한다.

 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

 아래는 그 예이다.

 public class <<당신의 Activity이름>> extends Activity { 

    /** Called when the activity is first created. */ 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        


        requestWindowFeature(Window.FEATURE_NO_TITLE); 


        Preview mPreview = new Preview(this); 

        /////여기에 삽입//////////////////////// 

        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        ////////////////////////////////////

        setContentView(mPreview);

        

    } 

}



  이 문장을 넣고 시험한 결과 정상 동작하는 것을 확인했다.

  카메라로 테스트 하시는 분들은 참조하시길...