From 17abc3833a43dd45e0801ccc539e226155f55ebf Mon Sep 17 00:00:00 2001 From: yrom Date: Tue, 9 Jan 2018 12:19:03 +0800 Subject: [PATCH] Audio recording is optional --- .../net/yrom/screenrecorder/MainActivity.java | 46 ++++++-- .../yrom/screenrecorder/Notifications.java | 2 +- .../yrom/screenrecorder/ScreenRecorder.java | 21 ++-- app/src/main/res/layout/activity_main.xml | 104 ++++++++++-------- 4 files changed, 108 insertions(+), 65 deletions(-) diff --git a/app/src/main/java/net/yrom/screenrecorder/MainActivity.java b/app/src/main/java/net/yrom/screenrecorder/MainActivity.java index caaaf4c..3b24e82 100644 --- a/app/src/main/java/net/yrom/screenrecorder/MainActivity.java +++ b/app/src/main/java/net/yrom/screenrecorder/MainActivity.java @@ -44,6 +44,7 @@ import android.widget.Button; import android.widget.SpinnerAdapter; import android.widget.Toast; +import android.widget.ToggleButton; import net.yrom.screenrecorder.view.NamedSpinner; @@ -67,6 +68,7 @@ public class MainActivity extends Activity { // members below will be initialized in onCreate() private MediaProjectionManager mMediaProjectionManager; private Button mButton; + private ToggleButton mAudioToggle; private NamedSpinner mVieoResolution; private NamedSpinner mVideoFramerate; private NamedSpinner mIFrameInterval; @@ -113,6 +115,9 @@ protected void onCreate(Bundle savedInstanceState) { mAudioCodec.setAdapter(codecsAdapter); restoreSelections(mAudioCodec, mAudioChannelCount); }); + mAudioToggle.setChecked( + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) + .getBoolean(getResources().getResourceEntryName(mAudioToggle.getId()), true)); } @Override @@ -142,8 +147,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } VideoEncodeConfig video = createVideoConfig(); - AudioEncodeConfig audio = createAudioConfig(); - if (video == null || audio == null) { + AudioEncodeConfig audio = createAudioConfig(); // audio can be null + if (video == null) { toast("Create ScreenRecorder failure"); mediaProjection.stop(); return; @@ -207,6 +212,7 @@ public void onRecording(long presentationTimeUs) { } private AudioEncodeConfig createAudioConfig() { + if (!mAudioToggle.isChecked()) return null; String codec = getSelectedAudioCodec(); if (codec == null) { return null; @@ -246,11 +252,14 @@ private static File getSavingDir() { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_PERMISSIONS) { - // we request 2 permissions - if (grantResults.length == 2 - && grantResults[0] == PackageManager.PERMISSION_GRANTED - && grantResults[1] == PackageManager.PERMISSION_GRANTED) { + int granted = PackageManager.PERMISSION_GRANTED; + for (int r : grantResults) { + granted |= r; + } + if (granted == PackageManager.PERMISSION_GRANTED) { startCaptureIntent(); + } else { + toast("No Permission!"); } } } @@ -285,6 +294,12 @@ private void bindViews() { mAudioProfile = findViewById(R.id.aac_profile); mAudioChannelCount = findViewById(R.id.audio_channel_count); + mAudioToggle = findViewById(R.id.with_audio); + mAudioToggle.setOnCheckedChangeListener((buttonView, isChecked) -> + findViewById(R.id.audio_format_chooser) + .setVisibility(isChecked ? View.VISIBLE : View.GONE) + ); + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { mOrientation.setSelectedPosition(1); } @@ -351,16 +366,22 @@ private void cancelRecorder() { @TargetApi(M) private void requestPermissions() { - if (!shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE) - && !shouldShowRequestPermissionRationale(RECORD_AUDIO)) { - requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE, RECORD_AUDIO}, REQUEST_PERMISSIONS); + String[] permissions = mAudioToggle.isChecked() + ? new String[]{WRITE_EXTERNAL_STORAGE, RECORD_AUDIO} + : new String[]{WRITE_EXTERNAL_STORAGE}; + boolean showRationale = false; + for (String perm : permissions) { + showRationale |= shouldShowRequestPermissionRationale(perm); + } + if (!showRationale) { + requestPermissions(permissions, REQUEST_PERMISSIONS); return; } new AlertDialog.Builder(this) .setMessage("Using your mic to record audio and your sd card to save video file") .setCancelable(false) .setPositiveButton(android.R.string.ok, (dialog, which) -> - requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE, RECORD_AUDIO}, REQUEST_PERMISSIONS)) + requestPermissions(permissions, REQUEST_PERMISSIONS)) .setNegativeButton(android.R.string.cancel, null) .create() .show(); @@ -369,7 +390,7 @@ private void requestPermissions() { private boolean hasPermissions() { PackageManager pm = getPackageManager(); String packageName = getPackageName(); - int granted = pm.checkPermission(RECORD_AUDIO, packageName) + int granted = (mAudioToggle.isChecked() ? pm.checkPermission(RECORD_AUDIO, packageName) : PackageManager.PERMISSION_GRANTED) | pm.checkPermission(WRITE_EXTERNAL_STORAGE, packageName); return granted == PackageManager.PERMISSION_GRANTED; } @@ -787,6 +808,7 @@ private void saveSelections() { }) { saveSelectionToPreferences(edit, spinner); } + edit.putBoolean(getResources().getResourceEntryName(mAudioToggle.getId()), mAudioToggle.isChecked()); edit.apply(); } @@ -817,7 +839,7 @@ public void onReceive(Context context, Intent intent) { if (ACTION_STOP.equals(intent.getAction())) { stopRecorder(); } - Toast.makeText(context, "Recorder stopped!", Toast.LENGTH_SHORT).show(); + Toast.makeText(context, "Recorder stopped!\n Saved file " + file, Toast.LENGTH_LONG).show(); StrictMode.VmPolicy vmPolicy = StrictMode.getVmPolicy(); try { // disable detecting FileUriExposure on public file diff --git a/app/src/main/java/net/yrom/screenrecorder/Notifications.java b/app/src/main/java/net/yrom/screenrecorder/Notifications.java index f1ffd73..e5fa1d2 100644 --- a/app/src/main/java/net/yrom/screenrecorder/Notifications.java +++ b/app/src/main/java/net/yrom/screenrecorder/Notifications.java @@ -85,7 +85,7 @@ private Notification.Builder getBuilder() { @TargetApi(O) private void createNotificationChannel() { NotificationChannel channel = - new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); + new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW); channel.setShowBadge(false); getNotificationManager().createNotificationChannel(channel); } diff --git a/app/src/main/java/net/yrom/screenrecorder/ScreenRecorder.java b/app/src/main/java/net/yrom/screenrecorder/ScreenRecorder.java index 9139c82..88d68e7 100644 --- a/app/src/main/java/net/yrom/screenrecorder/ScreenRecorder.java +++ b/app/src/main/java/net/yrom/screenrecorder/ScreenRecorder.java @@ -90,7 +90,7 @@ public ScreenRecorder(VideoEncodeConfig video, mMediaProjection = mp; mDstPath = dstPath; mVideoEncoder = new VideoEncoder(video); - mAudioEncoder = new MicRecorder(audio); + mAudioEncoder = audio == null ? null : new MicRecorder(audio); } @@ -331,12 +331,13 @@ private void resetAudioOutputFormat(MediaFormat newFormat) { } private void startMuxerIfReady() { - if (mMuxerStarted || mVideoOutputFormat == null || mAudioOutputFormat == null) { + if (mMuxerStarted || mVideoOutputFormat == null + || (mAudioEncoder != null && mAudioOutputFormat == null)) { return; } mVideoTrackIndex = mMuxer.addTrack(mVideoOutputFormat); - mAudioTrackIndex = mMuxer.addTrack(mAudioOutputFormat); + mAudioTrackIndex = mAudioEncoder == null ? INVALID_INDEX : mMuxer.addTrack(mAudioOutputFormat); mMuxer.start(); mMuxerStarted = true; if (VERBOSE) Log.i(TAG, "Started media muxer, videoIndex=" + mVideoTrackIndex); @@ -349,9 +350,11 @@ private void startMuxerIfReady() { int index = mPendingVideoEncoderBufferIndices.poll(); muxVideo(index, info); } - while ((info = mPendingAudioEncoderBufferInfos.poll()) != null) { - int index = mPendingAudioEncoderBufferIndices.poll(); - muxAudio(index, info); + if (mAudioEncoder != null) { + while ((info = mPendingAudioEncoderBufferInfos.poll()) != null) { + int index = mPendingAudioEncoderBufferIndices.poll(); + muxAudio(index, info); + } } if (VERBOSE) Log.i(TAG, "Mux pending video output buffers done."); } @@ -390,6 +393,8 @@ public void onOutputFormatChanged(BaseEncoder codec, MediaFormat format) { } private void prepareAudioEncoder() throws IOException { + final MicRecorder micRecorder = mAudioEncoder; + if (micRecorder == null) return; AudioEncoder.Callback callback = new AudioEncoder.Callback() { boolean ranIntoError = false; @@ -422,8 +427,8 @@ public void onError(Encoder codec, Exception e) { }; - mAudioEncoder.setCallback(callback); - mAudioEncoder.prepare(); + micRecorder.setCallback(callback); + micRecorder.prepare(); } private void signalStop(boolean stopWithEOS) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4c317c6..bb9e3a0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,4 +1,4 @@ - - - - - - - - - - - - - + android:orientation="vertical"> + + + + + + + + + + + + + + +