Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash onClick of Start recording #6

Closed
ritesh-karmare opened this issue Feb 20, 2020 · 22 comments
Closed

Crash onClick of Start recording #6

ritesh-karmare opened this issue Feb 20, 2020 · 22 comments

Comments

@ritesh-karmare
Copy link

Hi @HBiSoft ,

I executed the HBRecorder Example, on click of start button, the app crashes (irrespective of customSettings on/off).

  • Device : Moto G7 Power
  • Operation System : Android 9 (Pie)
  • All permissions are given

So in logs I can see 2 exceptions:

  1. FileNotFoundException
  2. IllegalStateException : failed to get the surface

Following are the logs:

2020-02-20 14:54:59.622 17493-17493/com.hbisoft.hbrecorderexample E/MediaRecorder: SurfaceMediaSource could not be initialized!
2020-02-20 14:54:59.623 17493-17493/com.hbisoft.hbrecorderexample E/MediaRecorder: start called in an invalid state: 4
2020-02-20 14:54:59.626 17493-17493/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.io.FileNotFoundException: /storage/emulated/0/Movies/HBRecorder/HD2020-02-20-14-54-59.mp4: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:485)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:288)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:151)
        at android.media.MediaRecorder.prepare(MediaRecorder.java:959)
        at com.hbisoft.hbrecorder.ScreenRecordService.initRecorder(ScreenRecordService.java:385)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:166)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
     Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:210)
        at libcore.io.IoBridge.open(IoBridge.java:471)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:288) 
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:151) 
        at android.media.MediaRecorder.prepare(MediaRecorder.java:959) 
        at com.hbisoft.hbrecorder.ScreenRecordService.initRecorder(ScreenRecordService.java:385) 
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:166) 
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884) 
        at android.app.ActivityThread.access$1700(ActivityThread.java:213) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6923) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870) 
2020-02-20 14:54:59.628 17493-17493/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.lang.IllegalStateException: failed to get surface
        at android.media.MediaRecorder.getSurface(Native Method)
        at com.hbisoft.hbrecorder.ScreenRecordService.initVirtualDisplay(ScreenRecordService.java:392)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:186)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
2020-02-20 14:54:59.629 17493-17493/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.lang.IllegalStateException
        at android.media.MediaRecorder.start(Native Method)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:206)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

Please try and change

path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES));

To:

path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));

@ritesh-karmare
Copy link
Author

ritesh-karmare commented Feb 20, 2020

@HBiSoft Thanks, thats fixed now.

However, there are two more exceptions:

2020-02-20 15:46:10.490 28330-28330/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.io.IOException: prepare failed.
        at android.media.MediaRecorder._prepare(Native Method)
        at android.media.MediaRecorder.prepare(MediaRecorder.java:978)
        at com.hbisoft.hbrecorder.ScreenRecordService.initRecorder(ScreenRecordService.java:385)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:166)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)

2020-02-20 15:46:10.492 28330-28330/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.lang.IllegalStateException: failed to get surface
        at android.media.MediaRecorder.getSurface(Native Method)
        at com.hbisoft.hbrecorder.ScreenRecordService.initVirtualDisplay(ScreenRecordService.java:392)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:186)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)

2020-02-20 15:46:10.494 28330-28330/com.hbisoft.hbrecorderexample E/HBRecorderOnError: java.lang.IllegalStateException
        at android.media.MediaRecorder.start(Native Method)
        at com.hbisoft.hbrecorder.ScreenRecordService.onStartCommand(ScreenRecordService.java:206)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3884)
        at android.app.ActivityThread.access$1700(ActivityThread.java:213)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1847)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6923)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

Try and disable the audio and see if the first issue goes away.

@ritesh-karmare
Copy link
Author

No changes. Still both the issues exists

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

It has something to do with the parameters set, I will look into this and get back to you. In the meantime you can try custom settings and see if there is any settings that works on your device.

@ritesh-karmare
Copy link
Author

ritesh-karmare commented Feb 20, 2020

@HBiSoft
This is the device width x height = 720 x 1371
recorder.setVideoSize(width, height);
It throws the illegalStateExceptionError : unable to get surface

However, when we set a valid resolution like 480 * 854, 720 * 1280 etc as recorder.videoSize and set it while creating virtualDisplay, it is working fine!!!

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

However, when we set a valid resolution like 480 * 854, 720 * 1280

How did you get this dimensions?

@ritesh-karmare
Copy link
Author

These dimensions I took from your sample.
Basically, 640 x 360, 854 x 480, 1280 x 720, 1920 x 1080 have an aspect ratio of 16:9, which is what I had required for screen recording.

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

Ah ok, I see what the problem is. I set the width and height to be the same as the screen dimension -

But this does not mean it is supported by the device, I will update the application later today.

@ritesh-karmare
Copy link
Author

Sure. I will look forward to it.

Thanks.

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 20, 2020

Can you test something for me? ->

Create a class in any project and call it HBRecorderCodecInfo and paste the following in that class:

import android.content.Context;
import android.content.res.Configuration;
import android.media.CamcorderProfile;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import androidx.annotation.RequiresApi;


import static android.content.Context.WINDOW_SERVICE;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;

public class HBRecorderCodecInfo {

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void getSupportedSizes(){
        RecordingInfo recordingInfo = getRecordingInfo();
        Log.e("MaxSupportedSizes --", "WIDTH = "+recordingInfo.width + " HEIGHT = "+recordingInfo.height);
    }

    private RecordingInfo getRecordingInfo() {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
        wm.getDefaultDisplay().getRealMetrics(displayMetrics);
        int displayWidth = displayMetrics.widthPixels;
        int displayHeight = displayMetrics.heightPixels;
        int displayDensity = displayMetrics.densityDpi;

        Configuration configuration = context.getResources().getConfiguration();
        boolean isLandscape = configuration.orientation == ORIENTATION_LANDSCAPE;

        CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        int cameraWidth = camcorderProfile != null ? camcorderProfile.videoFrameWidth : -1;
        int cameraHeight = camcorderProfile != null ? camcorderProfile.videoFrameHeight : -1;
        int cameraFrameRate = camcorderProfile != null ? camcorderProfile.videoFrameRate : 30;


        return calculateRecordingInfo(displayWidth, displayHeight, displayDensity, isLandscape,
                cameraWidth, cameraHeight, cameraFrameRate, 100);
    }

    private Context context;

    public void setContext(Context c) {
        context = c;
    }

    static final class RecordingInfo {
        final int width;
        final int height;
        final int frameRate;
        final int density;

        RecordingInfo(int width, int height, int frameRate, int density) {
            this.width = width;
            this.height = height;
            this.frameRate = frameRate;
            this.density = density;
        }
    }

    static RecordingInfo calculateRecordingInfo(int displayWidth, int displayHeight, int displayDensity, boolean isLandscapeDevice, int cameraWidth, int cameraHeight, int cameraFrameRate, int sizePercentage) {
        // Scale the display size before any maximum size calculations.
        displayWidth = displayWidth * sizePercentage / 100;
        displayHeight = displayHeight * sizePercentage / 100;

        if (cameraWidth == -1 && cameraHeight == -1) {
            // No cameras. Fall back to the display size.
            return new RecordingInfo(displayWidth, displayHeight, cameraFrameRate, displayDensity);
        }

        int frameWidth = isLandscapeDevice ? cameraWidth : cameraHeight;
        int frameHeight = isLandscapeDevice ? cameraHeight : cameraWidth;
        if (frameWidth >= displayWidth && frameHeight >= displayHeight) {
            // Frame can hold the entire display. Use exact values.
            return new RecordingInfo(displayWidth, displayHeight, cameraFrameRate, displayDensity);
        }

        // Calculate new width or height to preserve aspect ratio.
        if (isLandscapeDevice) {
            frameWidth = displayWidth * frameHeight / displayHeight;
        } else {
            frameHeight = displayHeight * frameWidth / displayWidth;
        }
        return new RecordingInfo(frameWidth, frameHeight, cameraFrameRate, displayDensity);
    }
}

Now in your Activity onCreate add the following:

HBRecorderCodecInfo hbRecorderCodecInfo = new HBRecorderCodecInfo();
hbRecorderCodecInfo.setContext(this);
hbRecorderCodecInfo.getSupportedSizes();

Run the application and let me know what the log says, it will be something like:

MaxSupportedSizes --: WIDTH = 864 HEIGHT = 1536

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 21, 2020

@ritesh-karmare
Did you see my previous comment?

@ritesh-karmare
Copy link
Author

@HBiSoft
Sorry, missed the comment somehow.
I executed the above code, its printing the following:
MaxSupportedSizes --: WIDTH = 720 HEIGHT = 1520

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 21, 2020

@ritesh-karmare
Thank you.
Can you change:

mMediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);

to

mMediaRecorder.setVideoSize(720, 1520);

and see if it is working?

@ritesh-karmare
Copy link
Author

Yes, I did. And it's working!

@HBiSoft
Copy link
Owner

HBiSoft commented Feb 21, 2020

Ok I will be updating later today, until then you can use the class above to determine the dimensions if you do not want to wait for the update.

@ritesh-karmare
Copy link
Author

Sure. I will consider it as resolved and close the issue
Thanks for the support @HBiSoft.

HBiSoft added a commit that referenced this issue Feb 21, 2020
HBiSoft added a commit that referenced this issue Feb 21, 2020
@HBiSoft
Copy link
Owner

HBiSoft commented Feb 21, 2020

This is now fixed in 0.1.6. You do not have to set the screen dimensions, it will select the highest value supported by your device.

@vivek-mittal
Copy link

Hi HBBiSoft, In your first comment above, you mentioned changing code inside ScreenRecordService.java, that is a class inside the lib, are you not planning to post an update?

Please try and change

path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES));

To:

path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));

@HBiSoft
Copy link
Owner

HBiSoft commented Mar 31, 2023

@vivek-mittal
You can change the directory using hbRecorder.setOutputUri(Uri);.

path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)); is only used when no directory was set.

@vivek-mittal
Copy link

Got it. But I am not using setOutputUri. I am using setOutputPath instead. Using it on both Android >=R and <R. I hope this will fix the crash. I do not have steps to reproduce the crash.

@HBiSoft
Copy link
Owner

HBiSoft commented Apr 1, 2023

@vivek-mittal
Have a look at the demo app.

ContentResolver resolver;
ContentValues contentValues;
Uri mUri;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void setOutputPath() {
String filename = generateFileName();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
resolver = getContentResolver();
contentValues = new ContentValues();
contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/" + "HBRecorder");
contentValues.put(MediaStore.Video.Media.TITLE, filename);
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
mUri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
//FILE NAME SHOULD BE THE SAME
hbRecorder.setFileName(filename);
hbRecorder.setOutputUri(mUri);
}else{
createFolder();
hbRecorder.setOutputPath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) +"/HBRecorder");
}
}

I would recommend implementing it like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants