4

I have the method below, and it works fine for the internal storage and external SD card on Android 4.3 or older:

    public void Recorder_Prepare() {        
        recorder = new MediaRecorder();
        recorder.setPreviewDisplay(holder.getSurface());
        mCamera.unlock();
        recorder.setCamera(mCamera);
        recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        recorder.setProfile(camcorderProfile);
        recorder.setVideoSize(ResolutionWidth, ResolutionHeight);

        File DirectoryExistCheck = new File(VideoFolderAbsolutePATH);
        if(!DirectoryExistCheck.exists()) {
            DirectoryExistCheck.mkdir();
        }

        String VideoPath = VideoFolderAbsolutePATH + separator + "Video.mp4"; 
        File NewVideoFile = new File(VideoPath);
        recorder.setOutputFile(NewVideoFile.getAbsolutePath());

        recorder.setVideoFrameRate(camcorderProfile.videoFrameRate);

          try {
              recorder.prepare();
          } 
          catch (IllegalStateException e) {
              Log.e("MyTag", "IllegalStateException : " + Log.getStackTraceString(e)); }        
          catch (IOException e) { 
              Log.e("MyTag", "IOException : " + Log.getStackTraceString(e)); } 

            recorder.start();
    }

........

........

Now I am picking a folder using the New Storage Access Framework for Android 5.0+:

    public void FolderSelection_Lollipop() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        startActivityForResult(intent, PICK_FOLDER_CODE_Lollipop);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {  
        if(requestCode == PICK_FOLDER_CODE_Lollipop) {
            if(resultCode == RESULT_OK) {
                // Get Uri from Storage Access Framework.
                Uri Uri_Lollipop = resultData.getData();    
                VideoFolderAbsolutePATH = Uri_Lollipop.getPath();
                //also tried:
                VideoFolderAbsolutePATH = Uri_Lollipop.toString();

                // Persist access permissions.
                this.getContentResolver().takePersistableUriPermission(Uri_Lollipop,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            }
        }
    }

The Recorder_Prepare() method no long works as it is giving me the IllegalStateException on Android 5.0+ :-(

I have also tried to follow the steps from this link:

Saving a video file with FileDesriptor

Same results...

The new SAF seems to be a mess for me although I have already tried to do my research online.

Does anyone know a work around or solution for this?

Thank you so much for your help and your kindness time.

....

Update: 6/8/16 at 10:41am

The link above actually works. It was an error with the Recorder_Prepare(), so I just moved stuff around and worked.

Community
  • 1
  • 1
Dante
  • 465
  • 2
  • 12
  • A `Uri` is not a file path, any more than a `URL` is. You are treating it as a file path, and that will not work. With regards to the `FileDescriptor` approach, you might consider editing your question to show that code, along with the full stack trace of your crash. – CommonsWare Jun 07 '16 at 20:23
  • @CommonsWare, thanks for your comment. I just updated my question. Thank you very much – Dante Jun 07 '16 at 20:53
  • That error does not sound like it comes directly from your use of `ACTION_CREATE_DOCUMENT`. Try continuing to use `ACTION_CREATE_DOCUMENT`, but then rather than using the `Uri` in `onActivityResult()`, substitute in your `File`-based logic from your first code snippet. If that gives the same "invalid preview surface" error, then the problem is not directly tied to `ACTION_CREATE_DOCUMENT`. Instead, your surface is having some issue after the SAF UI has come and gone. – CommonsWare Jun 07 '16 at 21:21
  • You were right that there was an issues with the Recorder_Prepare(). After I moved stuff around and it worked with FileDescriptor approach. I am going to edit my question to make it look better. Thank you for your help – Dante Jun 08 '16 at 15:40
  • "I am going to edit my question to make it look better" -- even better, post your own answer with your worked-out solution. – CommonsWare Jun 08 '16 at 16:00

1 Answers1

2

First, pick a folder and grant it permissions with the new Storage Access Framework API:

public void FolderSelection_Lollipop() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, PICK_FOLDER_CODE_Lollipop);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {  
    if(requestCode == PICK_FOLDER_CODE_Lollipop) {
        if(resultCode == RESULT_OK) {
            // Get Uri from Storage Access Framework.
            Uri Uri_Lollipop = resultData.getData();    
            // Persist access permissions.
            this.getContentResolver().takePersistableUriPermission(Uri_Lollipop,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
    }
}

......

......

public void Recorder_Prepare() {        
    recorder = new MediaRecorder();
    recorder.setPreviewDisplay(holder.getSurface());
    mCamera.unlock();
    recorder.setCamera(mCamera);
    recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    recorder.setProfile(camcorderProfile);
    recorder.setVideoSize(ResolutionWidth, ResolutionHeight);
    recorder.setVideoFrameRate(camcorderProfile.videoFrameRate);
    createFile(“Video.mp4”);
}

private void createFile(String fileName) {
    String mimeType = "video/mp4";
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);

    intent.addCategory(Intent.CATEGORY_OPENABLE);

    intent.setType(mimeType);
    intent.putExtra(Intent.EXTRA_TITLE, fileName);
    startActivityForResult(intent, WRITE_REQUEST_CODE 
}

@Override
public void onActivityResult(int requestCode, int resultCode,Intent resultData) {

    if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        if (resultData != null) {
            URI outputFileUri = resultData.getData();
            FileDescriptor outputFileDescriptor = getContentResolver().openFileDescriptor(outputFileUri, "w").getFileDescriptor()
            recorder.setOutputFile(outputFileDescriptor);

          try {
              recorder.prepare();
          } 
          catch (IllegalStateException e) {
              Log.e("MyTag", "IllegalStateException : " + Log.getStackTraceString(e)); }        
          catch (IOException e) { 
              Log.e("MyTag", "IOException : " + Log.getStackTraceString(e)); } 

            recorder.start();
        }
    }
}

It is not too much difference from the methods I posted in the question. I just moved stuff around, and it just worked. I hope it helps someone else. Thanks to Artem Pelenitsyn and CommonsWare for the comments.

Dante
  • 465
  • 2
  • 12