From b21fbe1c9c9566b0f3084373314668a399fe1764 Mon Sep 17 00:00:00 2001 From: tfrysinger Date: Tue, 6 Apr 2021 12:25:04 -0600 Subject: [PATCH] Added new Constants.java file to capture values used within HBRecorder Modified HBRecorder to utilize the above mentioned Constants Added maxFileSize property to HBRecorder, allowing it to be set from calling programs and having it passed along to ScreenRecordService. Updated HBRecorder to utilize int values for error codes as specified in Constants.java, including a new code indicating that the specified max file size has been reached (and have it automatically stop recording). Updated ScreenRecordService to utilize values from Constants.java Updated ScreenRecordService to implement setting a max file size on the media recorder. Added a string.xml resource to the hbrecorder module to capture strings used there. Updated gradle to target version 30. --- hbrecorder/build.gradle | 12 +-- .../com/hbisoft/hbrecorder/Constants.java | 15 ++++ .../com/hbisoft/hbrecorder/HBRecorder.java | 36 ++++++--- .../hbrecorder/ScreenRecordService.java | 76 ++++++++++++++----- hbrecorder/src/main/res/values/strings.xml | 3 + 5 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 hbrecorder/src/main/java/com/hbisoft/hbrecorder/Constants.java diff --git a/hbrecorder/build.gradle b/hbrecorder/build.gradle index bd85027..82bcd17 100644 --- a/hbrecorder/build.gradle +++ b/hbrecorder/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { minSdkVersion 17 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 1 versionName "1.0" @@ -26,8 +26,8 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.1.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.appcompat:appcompat:1.2.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/Constants.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/Constants.java new file mode 100644 index 0000000..397ec52 --- /dev/null +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/Constants.java @@ -0,0 +1,15 @@ +package com.hbisoft.hbrecorder; + +public class Constants { + public final static String MAX_FILE_SIZE_KEY = "maxFileSize"; + public final static String ERROR_REASON_KEY = "errorReason"; + public final static String ERROR_KEY = "error"; + public final static String ON_COMPLETE_KEY = "onComplete"; + public final static String ON_START_KEY = "onStart"; + public final static String ON_COMPLETE = "Uri was passed"; + public final static int SETTINGS_ERROR = 38; + public final static int MAX_FILE_SIZE_REACHED_ERROR = 48; + public final static int GENERAL_ERROR = 100; + public final static int ON_START = 111; + public final static int NO_SPECIFIED_MAX_SIZE = 0; +} diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java index 690fb07..964ace7 100644 --- a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/HBRecorder.java @@ -24,12 +24,19 @@ 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; + /** * Created by HBiSoft on 13 Aug 2019 * Copyright (c) 2019 . All rights reserved. */ -@SuppressWarnings("deprecation") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class HBRecorder implements MyListener { private int mScreenWidth; @@ -57,6 +64,7 @@ public class HBRecorder implements MyListener { private int videoBitrate = 40000000; private String outputFormat = "DEFAULT"; private int orientation; + private long maxFileSize = NO_SPECIFIED_MAX_SIZE; // Default no max size boolean wasOnErrorCalled = false; Intent service; boolean isPaused = false; @@ -85,6 +93,10 @@ public void setOutputUri(Uri uri){ mUri = uri; } + public void setMaxFileSize(long fileSize) { + maxFileSize = fileSize; + } + public boolean wasUriSet(){ return mWasUriSet; } @@ -311,19 +323,23 @@ private void startService(Intent data) { protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); if (resultCode == Activity.RESULT_OK) { - String errorListener = resultData.getString("errorReason"); - String onComplete = resultData.getString("onComplete"); - String onStart = resultData.getString("onStart"); - + String errorListener = resultData.getString(ERROR_REASON_KEY); + String onComplete = resultData.getString(ON_COMPLETE_KEY); + int onStartCode = resultData.getInt(ON_START_KEY); + int errorCode = resultData.getInt(ERROR_KEY); if (errorListener != null) { if (!mWasUriSet) { observer.stopWatching(); } wasOnErrorCalled = true; - hbRecorderListener.HBRecorderOnError(100, errorListener); + if ( errorCode > 0 ) { + hbRecorderListener.HBRecorderOnError(errorCode, errorListener); + } else { + hbRecorderListener.HBRecorderOnError(GENERAL_ERROR, errorListener); + } try { - Intent mservice = new Intent(context, ScreenRecordService.class); - context.stopService(mservice); + Intent mService = new Intent(context, ScreenRecordService.class); + context.stopService(mService); }catch (Exception e){ // Can be ignored } @@ -334,12 +350,14 @@ protected void onReceiveResult(int resultCode, Bundle resultData) { hbRecorderListener.HBRecorderOnComplete(); } wasOnErrorCalled = false; - }else if (onStart != null){ + }else if (onStartCode != 0){ hbRecorderListener.HBRecorderOnStart(); } } } }); + // Max file size + service.putExtra(MAX_FILE_SIZE_KEY, maxFileSize); context.startService(service); }catch (Exception e){ hbRecorderListener.HBRecorderOnError(0, Log.getStackTraceString(e)); diff --git a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/ScreenRecordService.java b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/ScreenRecordService.java index 17a7e77..a8f9030 100755 --- a/hbrecorder/src/main/java/com/hbisoft/hbrecorder/ScreenRecordService.java +++ b/hbrecorder/src/main/java/com/hbisoft/hbrecorder/ScreenRecordService.java @@ -35,16 +35,27 @@ import java.util.Locale; import java.util.Objects; +import static com.hbisoft.hbrecorder.Constants.ERROR_KEY; +import static com.hbisoft.hbrecorder.Constants.ERROR_REASON_KEY; +import static com.hbisoft.hbrecorder.Constants.MAX_FILE_SIZE_REACHED_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; +import static com.hbisoft.hbrecorder.Constants.ON_COMPLETE_KEY; +import static com.hbisoft.hbrecorder.Constants.ON_START; +import static com.hbisoft.hbrecorder.Constants.ON_START_KEY; +import static com.hbisoft.hbrecorder.Constants.SETTINGS_ERROR; + /** * Created by HBiSoft on 13 Aug 2019 * Copyright (c) 2019 . All rights reserved. */ -@SuppressWarnings("deprecation") public class ScreenRecordService extends Service { private static final String TAG = "ScreenRecordService"; - + private long maxFileSize = NO_SPECIFIED_MAX_SIZE; + private boolean hasMaxFileBeenReached = false; private int mScreenWidth; private int mScreenHeight; private int mScreenDensity; @@ -93,7 +104,9 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ //Start Recording else { //Get intent extras + hasMaxFileBeenReached = false; mIntent = intent; + maxFileSize = intent.getLongExtra(MAX_FILE_SIZE_KEY, NO_SPECIFIED_MAX_SIZE); byte[] notificationSmallIcon = intent.getByteArrayExtra("notificationSmallBitmap"); String notificationTitle = intent.getStringExtra("notificationTitle"); String notificationDescription = intent.getStringExtra("notificationDescription"); @@ -137,7 +150,7 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ audioSamplingRate = intent.getIntExtra("audioSamplingRate", 44100); String outputFormat = intent.getStringExtra("outputFormat"); if (outputFormat != null) { - setOutputformatAsInt(outputFormat); + setOutputFormatAsInt(outputFormat); } isCustomSettingsEnabled = intent.getBooleanExtra("enableCustomSettings", false); @@ -156,11 +169,11 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ } //Set notification title if developer did not if (notificationTitle == null || notificationTitle.equals("")) { - notificationTitle = "Recording your screen"; + notificationTitle = getString(R.string.stop_recording_notification_title); } //Set notification description if developer did not if (notificationDescription == null || notificationDescription.equals("")) { - notificationDescription = "Drag down to stop the recording"; + notificationDescription = getString(R.string.stop_recording_notification_message); } //Notification @@ -212,7 +225,7 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ } catch (Exception e) { ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("errorReason", Log.getStackTraceString(e)); + bundle.putString(ERROR_REASON_KEY, Log.getStackTraceString(e)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -224,7 +237,7 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ } catch (Exception e) { ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("errorReason", Log.getStackTraceString(e)); + bundle.putString(ERROR_REASON_KEY, Log.getStackTraceString(e)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -236,7 +249,7 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ } catch (Exception e) { ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("errorReason", Log.getStackTraceString(e)); + bundle.putString(ERROR_REASON_KEY, Log.getStackTraceString(e)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -244,23 +257,44 @@ else if (pauseResumeAction != null && pauseResumeAction.equals("resume")){ mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() { @Override - public void onError(MediaRecorder mediaRecorder, int i, int i1) { + public void onError(MediaRecorder mediaRecorder, int what, int extra) { + if ( what == 268435556 && hasMaxFileBeenReached) { + // Benign error b/c recording is too short and has no frames. See SO: https://stackoverflow.com/questions/40616466/mediarecorder-stop-failed-1007 + return; + } ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("error", "38"); - bundle.putString("errorReason", String.valueOf(i)); + bundle.putInt(ERROR_KEY, SETTINGS_ERROR); + bundle.putString(ERROR_REASON_KEY, String.valueOf(what)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } } }); + mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() { + @Override + public void onInfo(MediaRecorder mr, int what, int extra) { + if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { + hasMaxFileBeenReached = true; + Log.i(TAG,String.format(Locale.US,"onInfoListen what : %d | extra %d", what, extra)); + ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); + Bundle bundle = new Bundle(); + bundle.putInt(ERROR_KEY, MAX_FILE_SIZE_REACHED_ERROR); + bundle.putString(ERROR_REASON_KEY, getString(R.string.max_file_reached)); + if (receiver != null) { + receiver.send(Activity.RESULT_OK, bundle); + } + } + } + }); + //Start Recording try { mMediaRecorder.start(); ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("onStart", "111"); + bundle.putInt(ON_START_KEY, ON_START); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -268,8 +302,8 @@ public void onError(MediaRecorder mediaRecorder, int i, int i1) { // From the tests I've done, this can happen if another application is using the mic or if an unsupported video encoder was selected ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("error", "38"); - bundle.putString("errorReason", Log.getStackTraceString(e)); + bundle.putInt(ERROR_KEY, SETTINGS_ERROR); + bundle.putString(ERROR_REASON_KEY, Log.getStackTraceString(e)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -294,7 +328,7 @@ private void resumeRecording(){ //Set output format as int based on what developer has provided //It is important to provide one of the following and nothing else. - private void setOutputformatAsInt(String outputFormat) { + private void setOutputFormatAsInt(String outputFormat) { switch (outputFormat) { case "DEFAULT": outputFormatAsInt = 0; @@ -302,9 +336,6 @@ private void setOutputformatAsInt(String outputFormat) { case "THREE_GPP": outputFormatAsInt = 1; break; - case "MPEG_4": - outputFormatAsInt = 2; - break; case "AMR_NB": outputFormatAsInt = 3; break; @@ -323,6 +354,7 @@ private void setOutputformatAsInt(String outputFormat) { case "OGG": outputFormatAsInt = 11; break; + case "MPEG_4": default: outputFormatAsInt = 2; } @@ -455,7 +487,7 @@ private void initRecorder() throws Exception { } catch (Exception e) { ResultReceiver receiver = mIntent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("errorReason", Log.getStackTraceString(e)); + bundle.putString(ERROR_REASON_KEY, Log.getStackTraceString(e)); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } @@ -478,6 +510,10 @@ private void initRecorder() throws Exception { mMediaRecorder.setVideoFrameRate(videoFrameRate); } + // Catch approaching file limit + if ( maxFileSize > NO_SPECIFIED_MAX_SIZE) { + mMediaRecorder.setMaxFileSize(maxFileSize); // in bytes + } mMediaRecorder.prepare(); @@ -500,7 +536,7 @@ public void onDestroy() { private void callOnComplete() { ResultReceiver receiver = mIntent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER); Bundle bundle = new Bundle(); - bundle.putString("onComplete", "Uri was passed"); + bundle.putString(ON_COMPLETE_KEY, ON_COMPLETE); if (receiver != null) { receiver.send(Activity.RESULT_OK, bundle); } diff --git a/hbrecorder/src/main/res/values/strings.xml b/hbrecorder/src/main/res/values/strings.xml index c23246a..4602926 100644 --- a/hbrecorder/src/main/res/values/strings.xml +++ b/hbrecorder/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ HBRecorder + File size max has been reached. + Drag down to stop the recording + Recording your screen