Skip to content

Commit

Permalink
improved error catching (HBRecorderOnError)
Browse files Browse the repository at this point in the history
  • Loading branch information
HBiSoft committed Jan 14, 2020
1 parent b9fcd1e commit 9dd4684
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 82 deletions.
32 changes: 7 additions & 25 deletions app/src/main/java/com/hbisoft/hbrecorderexample/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Environment;
Expand Down Expand Up @@ -109,9 +107,6 @@ protected void onCreate(Bundle savedInstanceState) {
recordAudioCheckBoxListener();
notificationCheckboxListener();

MediaCodecInfo mediaCodecInfo = selectCodec("video/mp4");


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//Init HBRecorder
hbRecorder = new HBRecorder(this, this);
Expand All @@ -128,25 +123,6 @@ protected void onCreate(Bundle savedInstanceState) {

}

private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

if (!codecInfo.isEncoder()) {
continue;
}

String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
return codecInfo;
}
}
}
return null;
}

//Create Folder
private void createFolder() {
File f1 = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "HBRecorder");
Expand Down Expand Up @@ -247,14 +223,20 @@ public void HBRecorderOnComplete() {
}

@Override
public void HBRecorderOnError(int errorCode) {
public void HBRecorderOnError(int errorCode, String reason) {
// Error 38 happens when
// - the selected video encoder is not supported
// - the output format is not supported
// - if another app is using the microphone

//It is best to use device default

if (errorCode == 38){
showLongToast("Some settings are not supported by your device");
}else{
Log.e("HBRecorderOnError", reason);
}

startbtn.setText(R.string.start_recording);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,10 @@ private void startService(Intent data) {
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == Activity.RESULT_OK) {
String result = resultData.getString("error");
String result = resultData.getString("errorReason");
if (result != null) {
int errorCode = Integer.parseInt(result);
observer.stopWatching();
hbRecorderListener.HBRecorderOnError(errorCode);
hbRecorderListener.HBRecorderOnError(100, result);
Intent mservice = new Intent(context, ScreenRecordService.class);
context.stopService(mservice);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface HBRecorderListener {
void HBRecorderOnComplete();
void HBRecorderOnError(int errorCode);
void HBRecorderOnError(int errorCode, String reason);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import android.os.ResultReceiver;
import android.util.Log;

import java.io.IOException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;
Expand All @@ -54,24 +53,19 @@ public class ScreenRecordService extends Service {
private int audioSamplingRate;
private static String filePath;
private static String fileName;
private String audioSource;
private int audioSourceAsInt;
private String videoEncoder;
private int videoEncoderAsInt;
private boolean isCustomSettingsEnabled;
private int videoFrameRate;
private int videoBitrate;
private String outputFormat;
private int outputFormatAsInt;

public final static String BUNDLED_LISTENER = "listener";

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/*
* Notification Start
*/
public int onStartCommand(final Intent intent, int flags, int startId) {
//Get intent extras
byte[] notificationSmallIcon = intent.getByteArrayExtra("notificationSmallBitmap");
String notificationTitle = intent.getStringExtra("notificationTitle");
String notificationDescription = intent.getStringExtra("notificationDescription");
Expand All @@ -86,36 +80,39 @@ public int onStartCommand(Intent intent, int flags, int startId) {
isAudioEnabled = intent.getBooleanExtra("audio", true);
path = intent.getStringExtra("path");
name = intent.getStringExtra("fileName");
audioSource = intent.getStringExtra("audioSource");
videoEncoder = intent.getStringExtra("videoEncoder");
String audioSource = intent.getStringExtra("audioSource");
String videoEncoder = intent.getStringExtra("videoEncoder");
videoFrameRate = intent.getIntExtra("videoFrameRate",30);
videoBitrate = intent.getIntExtra("videoBitrate",40000000);

setAudioSourceAsInt(audioSource);
setvideoEncoderAsInt(videoEncoder);

filePath = name;
audioBitrate = intent.getIntExtra("audioBitrate", 128000);
audioSamplingRate = intent.getIntExtra("audioSamplingRate", 44100);
outputFormat = intent.getStringExtra("outputFormat");
String outputFormat = intent.getStringExtra("outputFormat");
setOutputformatAsInt(outputFormat);

isCustomSettingsEnabled = intent.getBooleanExtra("enableCustomSettings", false);

//Set notification notification button text if developer did not
if (notificationButtonText==null){
notificationButtonText = "STOP RECORDING";
}

//Set notification bitrate if developer did not
if (audioBitrate == 0){
audioBitrate = 128000;
}
//Set notification sampling rate if developer did not
if (audioSamplingRate == 0){
audioSamplingRate = 44100;
}

//Set notification title if developer did not
if (notificationTitle == null || notificationTitle.equals("")){
notificationTitle = "Recording your screen";
}

//Set notification description if developer did not
if (notificationDescription == null || notificationDescription.equals("")){
notificationDescription = "Drag down to stop the recording";
}
Expand Down Expand Up @@ -150,50 +147,78 @@ public int onStartCommand(Intent intent, int flags, int startId) {
} else {
//Modify notification badge
notification = new Notification.Builder(getApplicationContext(), channelId).setOngoing(true).setSmallIcon(R.drawable.icon).setContentTitle(notificationTitle).setContentText(notificationDescription).addAction(action).build();

}
startForeground(101, notification);
}
} else {
startForeground(101, new Notification());
}
}
/*
* Notification End
*/
//Notification End


if (path == null) {
path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES));
}

mMediaProjection = createMediaProjection();
mMediaRecorder = createMediaRecorder();
mVirtualDisplay = createVirtualDisplay();
//Init MediaRecorder
try {
initRecorder();
}catch (Exception e){
ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER);
Bundle bundle = new Bundle();
bundle.putString("errorReason", Log.getStackTraceString(e));
receiver.send(Activity.RESULT_OK, bundle);
}

//Init MediaProjection
try {
initMediaProjection();
}catch (Exception e){
ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER);
Bundle bundle = new Bundle();
bundle.putString("errorReason", Log.getStackTraceString(e));
receiver.send(Activity.RESULT_OK, bundle);
}

//Init VirtualDisplay
try {
initVirtualDisplay();
}catch (Exception e){
ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER);
Bundle bundle = new Bundle();
bundle.putString("errorReason", Log.getStackTraceString(e));
receiver.send(Activity.RESULT_OK, bundle);
}
mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mediaRecorder, int i, int i1) {
//TODO - Implement onError listener
Log.e("ERROR", "WAS CALLED");
ResultReceiver receiver = intent.getParcelableExtra(ScreenRecordService.BUNDLED_LISTENER);
Bundle bundle = new Bundle();
bundle.putString("error", "38");
bundle.putString("errorReason", String.valueOf(i));
receiver.send(Activity.RESULT_OK, bundle);
}
});

//Start Recording
try {
mMediaRecorder.start();
}catch (IllegalStateException e){
}catch (Exception e){
// 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));
receiver.send(Activity.RESULT_OK, bundle);
}


return Service.START_STICKY;
}

//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) {
switch (outputFormat) {
case "DEFAULT":
Expand Down Expand Up @@ -228,6 +253,8 @@ private void setOutputformatAsInt(String outputFormat) {
}
}

//Set video encoder as int based on what developer has provided
//It is important to provide one of the following and nothing else.
private void setvideoEncoderAsInt(String encoder) {
switch (encoder) {
case "DEFAULT":
Expand All @@ -251,6 +278,8 @@ private void setvideoEncoderAsInt(String encoder) {
}
}

//Set audio source as int based on what developer has provided
//It is important to provide one of the following and nothing else.
private void setAudioSourceAsInt(String audioSource) {
switch (audioSource) {
case "DEFAULT":
Expand Down Expand Up @@ -290,22 +319,22 @@ private void setAudioSourceAsInt(String audioSource) {
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private MediaProjection createMediaProjection() {
return ((MediaProjectionManager) Objects.requireNonNull(getSystemService(Context.MEDIA_PROJECTION_SERVICE))).
getMediaProjection(mResultCode, mResultData);
private void initMediaProjection(){
mMediaProjection = ((MediaProjectionManager) Objects.requireNonNull(getSystemService(Context.MEDIA_PROJECTION_SERVICE))).getMediaProjection(mResultCode, mResultData);
}

//Return the output file path as string
public static String getFilePath() {
return filePath;
}

//Return the name of the output file
public static String getFileName() {
return fileName;
}


@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private MediaRecorder createMediaRecorder() {
private void initRecorder() throws Exception{
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
Date curDate = new Date(System.currentTimeMillis());
String curTime = formatter.format(curDate).replace(" ", "");
Expand All @@ -321,50 +350,46 @@ private MediaRecorder createMediaRecorder() {

fileName = name + ".mp4";

MediaRecorder mediaRecorder = new MediaRecorder();
mMediaRecorder = new MediaRecorder();


if (isAudioEnabled) {
mediaRecorder.setAudioSource(audioSourceAsInt);
mMediaRecorder.setAudioSource(audioSourceAsInt);
}
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(outputFormatAsInt);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(outputFormatAsInt);
if (isAudioEnabled) {
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioEncodingBitRate(audioBitrate);
mediaRecorder.setAudioSamplingRate(audioSamplingRate);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setAudioEncodingBitRate(audioBitrate);
mMediaRecorder.setAudioSamplingRate(audioSamplingRate);
}

mediaRecorder.setVideoEncoder(videoEncoderAsInt);
mediaRecorder.setOutputFile(path + "/" + name + ".mp4");
mediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);
mMediaRecorder.setVideoEncoder(videoEncoderAsInt);
mMediaRecorder.setOutputFile(path + "/" + name + ".mp4");
mMediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);

if (!isCustomSettingsEnabled) {
if (!isVideoHD) {
mediaRecorder.setVideoEncodingBitRate(12000000);
mediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoEncodingBitRate(12000000);
mMediaRecorder.setVideoFrameRate(30);
} else {
mediaRecorder.setVideoEncodingBitRate(5 * mScreenWidth * mScreenHeight);
mediaRecorder.setVideoFrameRate(60); //after setVideoSource(), setOutFormat()
mMediaRecorder.setVideoEncodingBitRate(5 * mScreenWidth * mScreenHeight);
mMediaRecorder.setVideoFrameRate(60); //after setVideoSource(), setOutFormat()
}
}else{
mediaRecorder.setVideoEncodingBitRate(videoBitrate);
mediaRecorder.setVideoFrameRate(videoFrameRate);
mMediaRecorder.setVideoEncodingBitRate(videoBitrate);
mMediaRecorder.setVideoFrameRate(videoFrameRate);
}


try {
mediaRecorder.prepare();
} catch (IllegalStateException | IOException e) {
Log.e(TAG, "createMediaRecorder: e = " + e.toString());
}
mMediaRecorder.prepare();

return mediaRecorder;
//return mediaRecorder;
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay(TAG, mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
private void initVirtualDisplay(){
mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG, mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
Expand Down

0 comments on commit 9dd4684

Please sign in to comment.