From 57eab0c3b6dbe414cc07871559318ab96c17b496 Mon Sep 17 00:00:00 2001 From: abdulwahab1539 Date: Thu, 16 Jan 2025 22:03:12 +0500 Subject: [PATCH 1/2] Fixed Issue related to Black Bars on sides while recording video with custom resolution Changed resolution settings from dimensions to actual resolution options --- app/build.gradle | 2 +- .../hbrecorderexample/MainActivity.java | 15 ++- app/src/main/res/values/arrays.xml | 10 +- hbrecorder/build.gradle | 3 +- .../com/hbisoft/hbrecorder/HBRecorder.java | 106 ++++++++++-------- .../com/hbisoft/hbrecorder/WindowUtils.java | 70 ++++++++++++ 6 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java diff --git a/app/build.gradle b/app/build.gradle index d6358bd..2565597 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdk 34 defaultConfig { applicationId "com.hbisoft.hbrecorderexample" - minSdk 17 + minSdk 19 targetSdk 34 versionCode 1 versionName "1.0" diff --git a/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java b/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java index 295363e..871195d 100644 --- a/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java +++ b/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java @@ -468,19 +468,24 @@ private void customSettings() { if (video_resolution != null) { switch (video_resolution) { case "0": - hbRecorder.setScreenDimensions(426, 240); +// hbRecorder.setScreenDimensions(426, 240); + hbRecorder.setResolution(426); break; case "1": - hbRecorder.setScreenDimensions(640, 360); +// hbRecorder.setScreenDimensions(640, 360); + hbRecorder.setResolution(640); break; case "2": - hbRecorder.setScreenDimensions(854, 480); +// hbRecorder.setScreenDimensions(854, 480); + hbRecorder.setResolution(854); break; case "3": - hbRecorder.setScreenDimensions(1280, 720); +// hbRecorder.setScreenDimensions(1280, 720); + hbRecorder.setResolution(1280); break; case "4": - hbRecorder.setScreenDimensions(1920, 1080); + hbRecorder.setResolution(1920); +// hbRecorder.setScreenDimensions(1920, 1080); break; } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index e9f8575..80999ab 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -1,11 +1,11 @@ - 426x240 - 640x360 - 854x480 - 1280x720 - 1920x1080 + 240p + 360p + 480p + 720p + 1080p Default diff --git a/hbrecorder/build.gradle b/hbrecorder/build.gradle index a2163b0..d404b7d 100644 --- a/hbrecorder/build.gradle +++ b/hbrecorder/build.gradle @@ -5,7 +5,7 @@ android { compileSdk 34 defaultConfig { - minSdk 17 + minSdk 19 targetSdk 34 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -34,6 +34,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' testImplementation 'junit:junit:4.13.2' + implementation "androidx.window:window:1.2.0" androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java index b271d7d..36ca1b3 100644 --- a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java @@ -1,5 +1,15 @@ package com.hbisoft.hbrecorder; +import static com.hbisoft.hbrecorder.Constants.ERROR_KEY; +import static com.hbisoft.hbrecorder.Constants.ERROR_REASON_KEY; +import static com.hbisoft.hbrecorder.Constants.GENERAL_ERROR; +import static com.hbisoft.hbrecorder.Constants.MAX_FILE_SIZE_KEY; +import static com.hbisoft.hbrecorder.Constants.NO_SPECIFIED_MAX_SIZE; +import static com.hbisoft.hbrecorder.Constants.ON_COMPLETE_KEY; +import static com.hbisoft.hbrecorder.Constants.ON_PAUSE_KEY; +import static com.hbisoft.hbrecorder.Constants.ON_RESUME_KEY; +import static com.hbisoft.hbrecorder.Constants.ON_START_KEY; + import android.app.Activity; import android.app.ActivityManager; import android.content.Context; @@ -7,36 +17,23 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.CountDownTimer; import android.os.Environment; - -import androidx.annotation.DrawableRes; -import androidx.annotation.RequiresApi; - import android.os.Handler; import android.os.Looper; import android.os.ResultReceiver; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; +import androidx.annotation.DrawableRes; +import androidx.annotation.RequiresApi; import java.io.ByteArrayOutputStream; import java.io.File; -import static com.hbisoft.hbrecorder.Constants.ERROR_KEY; -import static com.hbisoft.hbrecorder.Constants.ERROR_REASON_KEY; -import static com.hbisoft.hbrecorder.Constants.GENERAL_ERROR; -import static com.hbisoft.hbrecorder.Constants.MAX_FILE_SIZE_KEY; -import static com.hbisoft.hbrecorder.Constants.NO_SPECIFIED_MAX_SIZE; -import static com.hbisoft.hbrecorder.Constants.ON_COMPLETE_KEY; -import static com.hbisoft.hbrecorder.Constants.ON_START_KEY; -import static com.hbisoft.hbrecorder.Constants.ON_PAUSE_KEY; -import static com.hbisoft.hbrecorder.Constants.ON_RESUME_KEY; - /** * Created by HBiSoft on 13 Aug 2019 * Copyright (c) 2019 . All rights reserved. @@ -83,7 +80,7 @@ public HBRecorder(Context context, HBRecorderListener listener) { setScreenDensity(); } - public void setOrientationHint(int orientationInDegrees){ + public void setOrientationHint(int orientationInDegrees) { orientation = orientationInDegrees; } @@ -94,8 +91,9 @@ public void setOutputPath(String path) { Uri mUri; boolean mWasUriSet = false; + @RequiresApi(api = Build.VERSION_CODES.Q) - public void setOutputUri(Uri uri){ + public void setOutputUri(Uri uri) { mWasUriSet = true; mUri = uri; } @@ -131,7 +129,7 @@ public void setOutputUri(Uri uri){ }*/ /*Set max duration in seconds */ - public void setMaxDuration(int seconds){ + public void setMaxDuration(int seconds) { isMaxDurationSet = true; maxDuration = seconds * 1000; } @@ -141,7 +139,7 @@ public void setMaxFileSize(long fileSize) { maxFileSize = fileSize; } - public boolean wasUriSet(){ + public boolean wasUriSet() { return mWasUriSet; } @@ -168,7 +166,7 @@ public void isAudioEnabled(boolean bool) { /*Set Audio Source*/ //MUST BE ONE OF THE FOLLOWING - https://developer.android.com/reference/android/media/MediaRecorder.AudioSource.html - public void setAudioSource(String source){ + public void setAudioSource(String source) { audioSource = source; } @@ -180,30 +178,30 @@ public void recordHDVideo(boolean bool) { /*Set Video Encoder*/ //MUST BE ONE OF THE FOLLOWING - https://developer.android.com/reference/android/media/MediaRecorder.VideoEncoder.html - public void setVideoEncoder(String encoder){ + public void setVideoEncoder(String encoder) { videoEncoder = encoder; } //Enable Custom Settings - public void enableCustomSettings(){ + public void enableCustomSettings() { enableCustomSettings = true; } //Set Video Frame Rate - public void setVideoFrameRate(int fps){ + public void setVideoFrameRate(int fps) { videoFrameRate = fps; } //Set Video BitRate - public void setVideoBitrate(int bitrate){ + public void setVideoBitrate(int bitrate) { videoBitrate = bitrate; } //Set Output Format //MUST BE ONE OF THE FOLLOWING - https://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html - public void setOutputFormat(String format){ + public void setOutputFormat(String format) { outputFormat = format; } @@ -214,25 +212,42 @@ private void setScreenDensity() { } //Get default width - public int getDefaultWidth(){ + public int getDefaultWidth() { HBRecorderCodecInfo hbRecorderCodecInfo = new HBRecorderCodecInfo(); hbRecorderCodecInfo.setContext(context); return hbRecorderCodecInfo.getMaxSupportedWidth(); } //Get default height - public int getDefaultHeight(){ + public int getDefaultHeight() { HBRecorderCodecInfo hbRecorderCodecInfo = new HBRecorderCodecInfo(); hbRecorderCodecInfo.setContext(context); return hbRecorderCodecInfo.getMaxSupportedHeight(); } //Set Custom Dimensions (NOTE - YOUR DEVICE MIGHT NOT SUPPORT THE SIZE YOU PASS IT) - public void setScreenDimensions(int heightInPX, int widthInPX){ + public void setScreenDimensions(int heightInPX, int widthInPX) { mScreenHeight = heightInPX; mScreenWidth = widthInPX; } + // Sets the Resolution of the video while maintaining device aspect ratio, + // HbRecorder onError will be called if dimensions are not supported by your device. + public void setResolution(int resolution) { + Pair customDimensions = + WindowUtils.getCustomDimensions( + resolution, + context.getApplicationContext() + ); + int targetWidth = customDimensions.first; + int height = customDimensions.second; + + Log.i("TAG", "setResolution: " + "Custom Dimensions: " + targetWidth + "x" + height); + + mScreenHeight = height; + mScreenWidth = targetWidth; + } + /*Get file path including file name and extension*/ public String getFilePath() { return ScreenRecordService.getFilePath(); @@ -257,8 +272,8 @@ public void stopScreenRecording() { /*Pause screen recording*/ @RequiresApi(api = Build.VERSION_CODES.N) - public void pauseScreenRecording(){ - if (service != null){ + public void pauseScreenRecording() { + if (service != null) { isPaused = true; service.setAction("pause"); context.startService(service); @@ -267,8 +282,8 @@ public void pauseScreenRecording(){ /*Pause screen recording*/ @RequiresApi(api = Build.VERSION_CODES.N) - public void resumeScreenRecording(){ - if (service != null){ + public void resumeScreenRecording() { + if (service != null) { isPaused = false; service.setAction("resume"); context.startService(service); @@ -276,7 +291,7 @@ public void resumeScreenRecording(){ } /*Check if video is paused*/ - public boolean isRecordingPaused(){ + public boolean isRecordingPaused() { return isPaused; } @@ -307,7 +322,7 @@ public void setNotificationSmallIconVector(@DrawableRes int VectorDrawable) { } /*Change notification icon using byte[]*/ - public void setNotificationSmallIcon(byte[] bytes) { + public void setNotificationSmallIcon(byte[] bytes) { byteArray = bytes; } @@ -321,7 +336,7 @@ public void setNotificationDescription(String Description) { notificationDescription = Description; } - public void setNotificationButtonText(String string){ + public void setNotificationButtonText(String string) { notificationButtonText = string; } @@ -361,7 +376,7 @@ private void startService(Intent data) { service.putExtra("notificationDescription", notificationDescription); service.putExtra("notificationButtonText", notificationButtonText); service.putExtra("enableCustomSettings", enableCustomSettings); - service.putExtra("audioSource",audioSource); + service.putExtra("audioSource", audioSource); service.putExtra("videoEncoder", videoEncoder); service.putExtra("videoFrameRate", videoFrameRate); @@ -384,7 +399,7 @@ protected void onReceiveResult(int resultCode, Bundle resultData) { observer.stopWatching(); } wasOnErrorCalled = true; - if ( errorCode > 0 ) { + if (errorCode > 0) { hbRecorderListener.HBRecorderOnError(errorCode, errorListener); } else { hbRecorderListener.HBRecorderOnError(GENERAL_ERROR, errorListener); @@ -392,13 +407,13 @@ protected void onReceiveResult(int resultCode, Bundle resultData) { try { Intent mService = new Intent(context, ScreenRecordService.class); context.stopService(mService); - }catch (Exception e){ + } catch (Exception e) { // Can be ignored } } // OnComplete was called - else if (onComplete != null){ + else if (onComplete != null) { //Stop countdown if it was set stopCountDown(); //OnComplete for when Uri was passed @@ -408,10 +423,10 @@ else if (onComplete != null){ wasOnErrorCalled = false; } // OnStart was called - else if (onStartCode != 0){ + else if (onStartCode != 0) { hbRecorderListener.HBRecorderOnStart(); //Check if max duration was set and start count down - if (isMaxDurationSet){ + if (isMaxDurationSet) { startCountdown(); } } @@ -431,7 +446,7 @@ else if (onStartCode != 0){ // Max file size service.putExtra(MAX_FILE_SIZE_KEY, maxFileSize); context.startService(service); - }catch (Exception e){ + } catch (Exception e) { hbRecorderListener.HBRecorderOnError(0, Log.getStackTraceString(e)); } @@ -439,6 +454,7 @@ else if (onStartCode != 0){ /*CountdownTimer for when max duration is set*/ Countdown countDown = null; + private void startCountdown() { countDown = new Countdown(maxDuration, 1000, 0) { @Override @@ -459,7 +475,7 @@ public void run() { stopScreenRecording(); observer.stopWatching(); hbRecorderListener.HBRecorderOnComplete(); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } } @@ -474,7 +490,7 @@ public void onStopCalled() { countDown.start(); } - private void stopCountDown(){ + private void stopCountDown() { if (countDown != null) { countDown.stop(); } diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java new file mode 100644 index 0000000..93b40ff --- /dev/null +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java @@ -0,0 +1,70 @@ +package com.hbisoft.hbrecorder; + +import android.content.Context; +import android.graphics.Rect; +import android.util.Log; +import android.util.Pair; + +import androidx.window.layout.WindowMetrics; +import androidx.window.layout.WindowMetricsCalculator; + +public class WindowUtils { + + /** + * Returns the Recording video width and height which makes up resolution. + * + * @param targetHeight takes target height and calculates the width according to the target + * height, while maintain device aspect ratio. + **/ + public static Pair getCustomDimensions(int targetHeight, Context context) { + + Pair deviceDimensions = getWindowSize(context); + int deviceWidth = deviceDimensions.first; + int deviceHeight = deviceDimensions.second; + + Log.i("TAG", "getCustomDimensions: " + deviceDimensions); + + float aspectRatio = (float) deviceWidth / deviceHeight; + + // Calculate the corresponding width for the target height + int targetWidth = (int) (targetHeight * aspectRatio); + + // Ensure the width is divisible by 16 + if (targetWidth % 16 != 0) { + targetWidth += (16 - targetWidth % 16); + } + + return new Pair<>(targetWidth, targetHeight); + } + + private static Pair getWindowSize(Context context) { + WindowMetricsCalculator calculator = WindowMetricsCalculator.getOrCreate(); + WindowMetrics metrics = calculator.computeMaximumWindowMetrics(context); + Rect bounds = metrics.getBounds(); + int width = bounds.width(); + int height = bounds.height(); + return new Pair<>(width, height); + } + + public static Pair getScaledDimensions( + int maxWidth, + int maxHeight, + float scaleFactor + ) { + if (scaleFactor <= 0 || scaleFactor > 1) { + scaleFactor = 0.8f; // Default value if invalid scaleFactor is passed + } + + float aspectRatio = (float) maxWidth / maxHeight; + + int newWidth = (int) (maxWidth * scaleFactor); + int newHeight = (int) (newWidth / aspectRatio); + + if (newHeight > (int) (maxHeight * scaleFactor)) { + newHeight = (int) (maxHeight * scaleFactor); + newWidth = (int) (newHeight * aspectRatio); + } + + return new Pair<>(newWidth, newHeight); + } +} From 38d17a9be31e28854e515f54617e2f74e8db7bd0 Mon Sep 17 00:00:00 2001 From: abdulwahab1539 Date: Fri, 7 Feb 2025 22:54:48 +0500 Subject: [PATCH 2/2] Black Bars Around the output videos fixed Added comments and function docs for better understanding what the function does and parameters it takes. new setResolution function documentation added in Readme --- README.md | 4 + .../hbrecorderexample/MainActivity.java | 126 +++++++++++------- .../com/hbisoft/hbrecorder/HBRecorder.java | 12 +- .../com/hbisoft/hbrecorder/WindowUtils.java | 12 +- 4 files changed, 100 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index fff71f9..ea7b748 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,10 @@ Then you can set the following: hbRecorder.setAudioSource(String); //MUST BE ONE OF THE FOLLOWING - https://developer.android.com/reference/android/media/MediaRecorder.VideoEncoder.html hbRecorder.setVideoEncoder(String); +//Use this If you want to set resolution of the video like 720 or 1080 etc. for example if you want your video to +//be of 1920x1080 then pass 1920 to this function it will calculate the width according to device resolution, +//while maintaining the aspect ratio. +hbRecorder.setResolution(HeightInPx); //If nothing is provided, it will select the highest value supported by your device hbRecorder.setScreenDimensions(HeightInPx, WidthInPx); //Frame rate is device dependent diff --git a/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java b/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java index 871195d..aebc380 100644 --- a/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java +++ b/app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java @@ -1,5 +1,9 @@ package com.hbisoft.hbrecorderexample; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static com.hbisoft.hbrecorder.Constants.MAX_FILE_SIZE_REACHED_ERROR; +import static com.hbisoft.hbrecorder.Constants.SETTINGS_ERROR; + import android.Manifest; import android.content.ContentResolver; import android.content.ContentValues; @@ -20,19 +24,18 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.RadioGroup; -import androidx.appcompat.widget.SwitchCompat; import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SwitchCompat; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -49,10 +52,6 @@ import java.util.Locale; import java.util.Map; -import static android.content.res.Configuration.ORIENTATION_PORTRAIT; -import static com.hbisoft.hbrecorder.Constants.MAX_FILE_SIZE_REACHED_ERROR; -import static com.hbisoft.hbrecorder.Constants.SETTINGS_ERROR; - /** * Created by HBiSoft on 13 Aug 2019 @@ -151,8 +150,8 @@ protected void onCreate(Bundle savedInstanceState) { Log.e("HBRecorderCodecInfo", "defaultVideoEncoder for (" + mMimeType + ") -> " + defaultVideoEncoder); Log.e("HBRecorderCodecInfo", "MaxSupportedFrameRate -> " + hbRecorderCodecInfo.getMaxSupportedFrameRate(mWidth, mHeight, mMimeType)); Log.e("HBRecorderCodecInfo", "MaxSupportedBitrate -> " + hbRecorderCodecInfo.getMaxSupportedBitrate(mMimeType)); - Log.e("HBRecorderCodecInfo", "isSizeAndFramerateSupported @ Width = "+mWidth+" Height = "+mHeight+" FPS = "+mFPS+" -> " + isSizeAndFramerateSupported); - Log.e("HBRecorderCodecInfo", "isSizeSupported @ Width = "+mWidth+" Height = "+mHeight+" -> " + hbRecorderCodecInfo.isSizeSupported(mWidth, mHeight, mMimeType)); + Log.e("HBRecorderCodecInfo", "isSizeAndFramerateSupported @ Width = " + mWidth + " Height = " + mHeight + " FPS = " + mFPS + " -> " + isSizeAndFramerateSupported); + Log.e("HBRecorderCodecInfo", "isSizeSupported @ Width = " + mWidth + " Height = " + mHeight + " -> " + hbRecorderCodecInfo.isSizeSupported(mWidth, mHeight, mMimeType)); Log.e("HBRecorderCodecInfo", "Default Video Format = " + hbRecorderCodecInfo.getDefaultVideoFormat()); HashMap supportedVideoMimeTypes = hbRecorderCodecInfo.getSupportedVideoMimeTypes(); @@ -169,7 +168,7 @@ protected void onCreate(Bundle savedInstanceState) { for (int j = 0; j < supportedVideoFormats.size(); j++) { Log.e("HBRecorderCodecInfo", "Available Video Formats : " + supportedVideoFormats.get(j)); } - }else{ + } else { Log.e("HBRecorderCodecInfo", "MimeType not supported"); } @@ -222,7 +221,7 @@ && checkSelfPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION, hasPermissions = true; saveAudioPreference(true); } - }else{ + } else { if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS, PERMISSION_REQ_POST_NOTIFICATIONS) && checkSelfPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION, PERMISSION_REQ_ID_FOREGROUND_SERVICE_MEDIA_PROJECTION)) { hasPermissions = true; @@ -236,7 +235,7 @@ && checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECOR hasPermissions = true; saveAudioPreference(true); } - }else{ + } else { if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS, PERMISSION_REQ_POST_NOTIFICATIONS)) { hasPermissions = true; } @@ -264,13 +263,13 @@ && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSION_RE } else { // else start recording if (!hasAudioPermissions && isAudioEnabled) { - if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)){ + if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)) { hasPermissions = true; saveAudioPreference(true); startRecordingScreen(); } - }else { + } else { startRecordingScreen(); } } @@ -324,12 +323,12 @@ public void HBRecorderOnComplete() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //Update gallery depending on SDK Level if (hbRecorder.wasUriSet()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { updateGalleryUri(); } else { refreshGalleryFile(); } - }else{ + } else { refreshGalleryFile(); } } @@ -348,7 +347,7 @@ public void HBRecorderOnError(int errorCode, String reason) { if (errorCode == SETTINGS_ERROR) { showLongToast(getString(R.string.settings_not_supported_message)); - } else if ( errorCode == MAX_FILE_SIZE_REACHED_ERROR) { + } else if (errorCode == MAX_FILE_SIZE_REACHED_ERROR) { showLongToast(getString(R.string.max_file_size_reached_message)); } else { showLongToast(getString(R.string.general_recording_error_message)); @@ -384,7 +383,7 @@ public void onScanCompleted(String path, Uri uri) { } @RequiresApi(api = Build.VERSION_CODES.Q) - private void updateGalleryUri(){ + private void updateGalleryUri() { contentValues.clear(); contentValues.put(MediaStore.Video.Media.IS_PENDING, 0); getContentResolver().update(mUri, contentValues, null, null); @@ -412,6 +411,7 @@ private void startRecordingScreen() { } String output_format; + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) // Example of how to set custom settings private void customSettings() { @@ -462,33 +462,8 @@ private void customSettings() { } } - //NOTE - THIS MIGHT NOT BE SUPPORTED SIZES FOR YOUR DEVICE - //Video Dimensions - String video_resolution = prefs.getString("key_video_resolution", null); - if (video_resolution != null) { - switch (video_resolution) { - case "0": -// hbRecorder.setScreenDimensions(426, 240); - hbRecorder.setResolution(426); - break; - case "1": -// hbRecorder.setScreenDimensions(640, 360); - hbRecorder.setResolution(640); - break; - case "2": -// hbRecorder.setScreenDimensions(854, 480); - hbRecorder.setResolution(854); - break; - case "3": -// hbRecorder.setScreenDimensions(1280, 720); - hbRecorder.setResolution(1280); - break; - case "4": - hbRecorder.setResolution(1920); -// hbRecorder.setScreenDimensions(1920, 1080); - break; - } - } +// setPrefsCustomDimensions(prefs); + setPrefCustomResolution(prefs); //Video Frame Rate String video_frame_rate = prefs.getString("key_video_fps", null); @@ -567,6 +542,58 @@ private void customSettings() { } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void setPrefCustomResolution(SharedPreferences prefs) { + String video_resolution = prefs.getString("key_video_resolution", null); + if (video_resolution != null) { + switch (video_resolution) { + case "0": + hbRecorder.setResolution(426); + break; + case "1": + hbRecorder.setResolution(640); + break; + case "2": + hbRecorder.setResolution(854); + break; + case "3": + hbRecorder.setResolution(1280); + break; + case "4": + hbRecorder.setResolution(1920); + break; + } + } + } + + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void setPrefsCustomDimensions(SharedPreferences prefs) { + //NOTE - THIS MIGHT NOT BE SUPPORTED SIZES FOR YOUR DEVICE, AND WILL INTRODUCE BLACK BARS + // ON SIDE OF VIDEOS + //Video Dimensions + String video_resolution = prefs.getString("key_video_resolution", null); + if (video_resolution != null) { + switch (video_resolution) { + case "0": + hbRecorder.setScreenDimensions(426, 240); + break; + case "1": + hbRecorder.setScreenDimensions(640, 360); + break; + case "2": + hbRecorder.setScreenDimensions(854, 480); + break; + case "3": + hbRecorder.setScreenDimensions(1280, 720); + break; + case "4": + hbRecorder.setScreenDimensions(1920, 1080); + break; + } + } + } + //Get/Set the selected settings @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void quickSettings() { @@ -634,7 +661,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (isAudioEnabled) { checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO); - }else { + } else { checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE); } } else { @@ -689,7 +716,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { //Start screen recording hbRecorder.startScreenRecording(data, resultCode); - }else{ + } else { startbtn.setText(R.string.start_recording); } } @@ -703,6 +730,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { ContentResolver resolver; ContentValues contentValues; Uri mUri; + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void setOutputPath() { String filename = generateFileName(); @@ -714,16 +742,16 @@ private void setOutputPath() { contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, filename); if (output_format != null) { contentValues.put(MediaStore.MediaColumns.MIME_TYPE, getMimeTypeForOutputFormat(output_format)); - }else { + } else { 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{ + } else { createFolder(); - hbRecorder.setOutputPath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) +"/HBRecorder"); + hbRecorder.setOutputPath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/HBRecorder"); } } diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java index 36ca1b3..25cd753 100644 --- a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java @@ -225,14 +225,20 @@ public int getDefaultHeight() { return hbRecorderCodecInfo.getMaxSupportedHeight(); } - //Set Custom Dimensions (NOTE - YOUR DEVICE MIGHT NOT SUPPORT THE SIZE YOU PASS IT) + /** + * Set Custom Dimensions (NOTE - YOUR DEVICE MIGHT NOT SUPPORT THE SIZE YOU PASS IT) + * Might introduce black bars (Padding) around or sides of the video if dimensions are not + * according to device aspect ratio + **/ public void setScreenDimensions(int heightInPX, int widthInPX) { mScreenHeight = heightInPX; mScreenWidth = widthInPX; } - // Sets the Resolution of the video while maintaining device aspect ratio, - // HbRecorder onError will be called if dimensions are not supported by your device. + /** + * Sets the Resolution of the video while maintaining device aspect ratio, + * HbRecorder onError will be called if dimensions are not supported by your device. + **/ public void setResolution(int resolution) { Pair customDimensions = WindowUtils.getCustomDimensions( diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java index 93b40ff..bf98944 100644 --- a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/WindowUtils.java @@ -14,7 +14,7 @@ public class WindowUtils { * Returns the Recording video width and height which makes up resolution. * * @param targetHeight takes target height and calculates the width according to the target - * height, while maintain device aspect ratio. + * height, while maintaining device aspect ratio. **/ public static Pair getCustomDimensions(int targetHeight, Context context) { @@ -29,7 +29,7 @@ public static Pair getCustomDimensions(int targetHeight, Conte // Calculate the corresponding width for the target height int targetWidth = (int) (targetHeight * aspectRatio); - // Ensure the width is divisible by 16 + // Ensure the width is divisible by 16 to prevent unsupported dimensions error. if (targetWidth % 16 != 0) { targetWidth += (16 - targetWidth % 16); } @@ -46,6 +46,14 @@ private static Pair getWindowSize(Context context) { return new Pair<>(width, height); } + /** + * Returns the Recording video width and height which makes up resolution. + * takes height and width for the video + * + * @param scaleFactor scales down the resolution (height & width) of the video according + * to the value provided to this parameter should be between 0 and 1 + * otherwise default is 0.8 means 80%. + **/ public static Pair getScaledDimensions( int maxWidth, int maxHeight,