도전과제 26 : 증강 현실로 쿠폰 보여주기 (Do it Android 앱 프로그래밍) [JAVA]
반응형

 

도전과제 26

증강 현실에서 쿠폰을 보여주는 화면을 가상으로 만들어보세요. 카메라 미리보기 화면을 보여주고 그 위에 쿠폰 이미지를 보여주면 증강 현실에서 보여주는 것처럼 만들 수 있습니다.

  1. 앱을 실행하면 카메라 미리보기 화면이 보이도록 하고 아래쪽에는 [쿠폰 보이기]와 [쿠폰 감추기] 버튼을 배치합니다.
  2. [쿠폰 보이기] 버튼을 누르면 카메라 미리보기 화면 위에 쿠폰 아이콘을 보여줍니다.
  3. [쿠폰 감추기] 버튼을 누르면 쿠폰 아이콘이 보이지 않도록 합니다.
  4. 쿠폰 아이콘을 선택하면 토스트 메시지로 선택된 쿠폰 정보를 간단하게 보여줍니다.
  5. 카메라 미리보기와 쿠폰 아이콘을 같이 보여주도록 프레임 레이아웃 안에 케메라 미리보기와 쿠폰 아이콘 두 개의 레이아웃을 준비합니다. 그런 다음 소스 코드에서 쿠폰 레이아웃의 visibility 속성을 조절합니다.

참고할점
증강 현실에서는 센서까지 사용해야 합니다. 여기에서는 센서는 사용하지 않고 카메라 미리보기 화면 위에 쿠폰 이미지를 보여주는 것까지만 해 봅니다. 센서를 사용하지 않기 때문에 단말을 움직여도 쿠폰 이미지가 따라서 움직이지는 않습니다.

 

풀이

쿠폰 아이콘을 따로 xml 파일로 지정하고 메인 레이아웃에서 카메라가 들어갈 FrameLayout 안에 버튼 형태로 쿠폰 아이콘을 넣어 두었다.

카메라 화면이 뜨게 하기 위해선, 우선 권한 설정이 필요하다. Manifest파일에 권한을 추가해준다. 또한 Github에 있는 AutoPermission library 역시 받아온다.

//Manifest
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
    
    
//build
allprojects{
    repositories{
        maven{url 'https://jitpack.io' }
    }
}
dependencies {
	//...
	implementation 'com.github.pedroSG94:AutoPermissions:1.0.3'
}

카메라 미리보기 화면은 서피스홀더가 프리뷰를 설정하면 -> 카메라에서 프리뷰를 시작하고 디스플레이하고 -> 서피스홀더에서 이 프리뷰를 서피스뷰로 보여줌으로써 이루어진다. 한마디로 서피스홀더를 통해 서피스뷰를 잘 조작해서 보여주는 것이다. 

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera camera = null;

		//생성될때 홀더 객체 참조
        public CameraSurfaceView(Context context) {	
            super(context);
            mHolder = getHolder();
            mHolder.addCallback(this);
        }

		//서피스뷰 만들어질 때 카메라객체 참조
        @Override
        public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
            camera = Camera.open();
            setCameraOrientation();
            try {
            	//이후 홀더 객체 설정
                camera.setPreviewDisplay(mHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void setCameraOrientation(){//화면도 같이 돌아가게
            if(camera == null) return;
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(0,info);
            WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            int rotation = manager.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);
        }
        
		//바뀔 때마다 계속 미리보기
        @Override
        public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            camera.startPreview();
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
            camera.stopPreview();
            camera.release();
            camera = null;
        }
        //사진 찍을때
        public boolean capture(Camera.PictureCallback handler){
            if(camera != null){
                camera.takePicture(null,null, handler);
                return true;
            }
            else{
                return false;
            }
        }
    }

우선 SurfaceVIew를 상속받고, SurfaceHolder.Callback을 구현한 클래스 CameraSurfaceView를 정의하였다. 이제 생성자에서 서피스홀더 객체 참조 후 설정하고 -> 서피스뷰가 만들어질 때 카메라 객체를 참조한 후 미리보기 화면으로 홀더 객체를 설정하고 -> 서피스뷰의 화면 크기가 바뀌는 등 변경될때 미리보기가 계속 시작되며 -> 서피스뷰가 사라질때 중지되는 방법으로 진행된다.

이후에 두 쿠폰을 버튼형태로 넣었기 때문에, 쿠폰 보여주기, 숨기기에 따라 버튼이 작동하게 하면 된다.

 

결과

처음에는 쿠폰을 비트맵으로 넣으려다 애먹었다..

 

전체 소스코드 : https://github.com/howtolivelikehuman/DoitAndroid/tree/master/DoitMission_26/app/src/main

 

howtolivelikehuman/DoitAndroid

Do it Android programing (JAVA). Contribute to howtolivelikehuman/DoitAndroid development by creating an account on GitHub.

github.com

 

반응형