마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

surface view 화면 캡처 질문입니다.

0 추천

검색을 해보니 많은 분들이 겪어본 문제이고 많이 어려운 문제인 것 같습니다... 

 

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";

    private static String EXTERNAL_STORAGE_PATH = "";
    private static String RECORDED_FILE = "video_recorded";
    private static int fileIndex = 0;
    private static String filename = "";
    MediaPlayer player;
    MediaRecorder recorder;
    private Camera camera;
    SurfaceHolder holder;
    Handler handler;             // 영상 캡쳐 핸들러
    boolean bRecord = false;   // 영상 녹화 상태 확인
    SurfaceView surface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       
        String state = Environment.getExternalStorageState();
        if (!state.equals(Environment.MEDIA_MOUNTED)) {
            Log.d(TAG, "External Storage Media is not mounted.");
        } else {
            EXTERNAL_STORAGE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
        }

        camera = Camera.open();
        // create a SurfaceView instance and add it to the layout
        surface = new SurfaceView(this);

        holder = surface.getHolder();
        holder.addCallback((SurfaceHolder.Callback) this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);



        frame = (FrameLayout) findViewById(R.id.videoLayout);
        frame.addView(surface);

        // Button ID
        Button recordBtn = (Button) findViewById(R.id.recordBtn);
        Button recordStopBtn = (Button) findViewById(R.id.recordStopBtn);
        Button playBtn = (Button) findViewById(R.id.playBtn);
        Button playStopBtn = (Button) findViewById(R.id.playStopBtn);


        // 녹화 시작
        recordBtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    if (recorder == null) {
                        recorder = new MediaRecorder();
                    }
                    bRecord = true;
                    
                    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    recorder.setVideoFrameRate(25);
                    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
                 

                    filename = createFilename();
                    recorder.setOutputFile(filename);

                    recorder.setPreviewDisplay(holder.getSurface());

                    handler = new Handler();
                    handler.postDelayed(new RunnableCapture(), 5000);

                    recorder.prepare();
                    recorder.start();

                } catch (Exception ex) {
                    Log.e(TAG, "Exception : ", ex);
                    recorder.release();
                    recorder = null;
                }
            }
        });

        // 녹화 중지
        recordStopBtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if (recorder == null)
                    return;
                bRecord = false;
                recorder.stop();
                recorder.reset();
                recorder.release();
                recorder = null;

                ContentValues values = new ContentValues(10);

                values.put(MediaStore.MediaColumns.TITLE, "RecordedVideo");
                values.put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis() / 1000);
                values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");

                Uri videoUri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
                if (videoUri == null) {
                    Log.d("SampleVideoRecorder", "Video insert failed.");
                    return;
                }

                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, videoUri));

            }
        });

    // 파일 이름.
    private String createFilename() {
        fileIndex++;

        String newFilename = "";
        if (EXTERNAL_STORAGE_PATH == null || EXTERNAL_STORAGE_PATH.equals("")) {
            // use internal memory
            newFilename = RECORDED_FILE + fileIndex + ".mp4";
        } else {
            newFilename = EXTERNAL_STORAGE_PATH + "/" + RECORDED_FILE + fileIndex + ".mp4";
        }

        return newFilename;
    }


    protected void onPause() {
        if (camera != null) {
            camera.release();
            camera = null;
        }

        if (recorder != null) {
            recorder.release();
            recorder = null;
        }

        if (player != null) {
            player.release();
            player = null;
        }

        super.onPause();
    }

    // 이미지 캡쳐 핸들러 함수.
    private class RunnableCapture implements Runnable {
        @Override
        public void run() {
            int width_frame = surface.getWidth();     // 캡쳐 당할 레이아웃 크기
            int height_frame = surface.getHeight();

            surface.setDrawingCacheEnabled(true);
            surface.buildDrawingCache(true);
            /************핵심 *************/
            Bitmap captureView = Bitmap.createBitmap(surface.getMeasuredWidth(), surface.getMeasuredHeight(), Bitmap.Config.ARGB_8888 );
            Canvas screenShootCanvas = new Canvas(captureView);

            surface.draw(screenShootCanvas);
 
            FileOutputStream fos;
            // 현재 날짜로 파일 저장하기
            SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
            //년월일시분초
            Date currentTime_1 = new Date();
            String filename = formatter.format(currentTime_1);

            File fileRoute = null;
            fileRoute = Environment.getExternalStorageDirectory();

            try{
                File path = new File(fileRoute, "temp");
                if(!path.exists()){
                    path.mkdirs();
                }
                fos = new FileOutputStream(fileRoute+"/temp/"+filename+".jpeg");
                captureView.compress(Bitmap.CompressFormat.JPEG, 100, fos);

                surface.setDrawingCacheEnabled(false);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            Toast.makeText(MainActivity.this, "save image", Toast.LENGTH_SHORT).show();
            if (bRecord) { // 아직도 녹화중이라면 캡쳐를 진행한다.
                handler.postDelayed(this, 5000);
            }
        }
    }
}

동영상이 녹화되는 동안 5초 간격으로 화면 캡처를 하고 싶습니다. 

surface view를 강제로 canvas로 바꾼 다음 실행하면 된다고 하는데.. .

다른 분들 소스랑 너무 달라서 어떻게 바꿔야 하는지 도통 감이 안 오네요 ㅠㅠ

제발 살려주세요 ㅠㅠ

khseob0715 (140 포인트) 님이 2017년 10월 29일 질문

1개의 답변

0 추천
녹화중이라. SurfaceView 속성을 바꾸는건 위험할 듯 합니다.

Camera API에서 사용하는 preview Callback을 사용해서 구하시는게 좋을 듯 합니다.

https://stackoverflow.com/questions/6743768/android-camera-preview-callback-and-mediarecorder-record-video

https://stackoverflow.com/questions/6743768/android-camera-preview-callback-and-mediarecorder-record-video
익명사용자 님이 2017년 10월 30일 답변
...