MediaRecorder 没有第二次录制
Posted
技术标签:
【中文标题】MediaRecorder 没有第二次录制【英文标题】:MediaRecorder not recording the second time 【发布时间】:2020-04-01 16:36:00 【问题描述】:我正在使用 MediaRecorder 记录用户屏幕。首次打开应用程序并且用户单击 fab 按钮记录屏幕时,一切正常。但是如果应用程序正在运行,用户再次单击记录按钮,在我想要的文件路径中不会生成新文件,因此我的列表视图不会更新。
如果我关闭该应用程序并再次运行该应用程序,则 mediarecorder 只能在第一次运行。我尝试了许多不同的方法,并在 Stack Overflow 上寻找解决方案,但都是徒劳的。第二次单击录制按钮时,我无法录制屏幕。我也没有收到任何错误。这是我的代码:
public class MainActivity extends AppCompatActivity
private static final String TAG = "MainActivity";
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
Button btn;
private int screenDensity;
private MediaProjectionManager mediaProjectionManager;
private MediaProjection mediaProjection;
private VirtualDisplay virtualDisplay;
private MediaProjection.Callback mediaProjectionCallback;
private MediaRecorder mediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private boolean isRecording = false;
static SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
static String todayDate = dateFormat.format(new Date());
static
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] PERMISSIONS = Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO;
if (!hasPermissions(this, PERMISSIONS))
ActivityCompat.requestPermissions(this, PERMISSIONS, 1);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
screenDensity = displayMetrics.densityDpi;
mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
btn = findViewById(R.id.fab);
btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
toggleScreenShare();
);
public static boolean hasPermissions(Context context, String... permissions)
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null)
for (String permission : permissions)
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
return false;
return true;
public void recordBtnReload()
if (isRecording)
btn.setText("Stop");
else
btn.setText("Record");
private void toggleScreenShare()
if (!isRecording)
initRecorder();
shareScreen();
else
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
stopScreenSharing();
private void stopScreenSharing()
if (virtualDisplay == null)
return;
virtualDisplay.release();
destroyMediaProjection();
isRecording = false;
recordBtnReload();
private void destroyMediaProjection()
if (mediaProjection != null)
mediaProjection.unregisterCallback(mediaProjectionCallback);
mediaProjection.stop();
mediaProjection = null;
Log.i(TAG, "MediaProjection is stopped for now");
private void shareScreen()
if (mediaProjection == null)
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 1000);
return;
virtualDisplay = createVirtualDisplay();
mediaRecorder.start();
isRecording = true;
recordBtnReload();
Log.i(TAG, "ShareScreen started for now");
private void initRecorder()
try
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudiosource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncodingBitRate(512 * 1000);
mediaRecorder.setVideoFrameRate(16);
mediaRecorder.setVideoEncodingBitRate(3000000);
String directory = Environment.getExternalStorageDirectory() + File.separator + "NewCapture";
File folder = new File(directory);
boolean success = true;
if (!folder.exists())
success = folder.mkdir();
String filepath;
if (success)
String videoName = ("Video_" + todayDate + ".mp4");
filepath = directory + File.separator + videoName;
Log.i(TAG, "File created");
else
Toast.makeText(this, "Failed to create Recordings directory", Toast.LENGTH_SHORT).show();
return;
mediaRecorder.setOutputFile(filepath);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mediaRecorder.setOrientationHint(orientation);
mediaRecorder.prepare();
Log.i(TAG, "initRecorder");
catch (IOException e)
e.printStackTrace();
private VirtualDisplay createVirtualDisplay()
Log.i(TAG, "Created Virtual Display");
return mediaProjection.createVirtualDisplay(TAG, DISPLAY_WIDTH, DISPLAY_HEIGHT, screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != 1000)
Log.e(TAG, "Unknown request code:" + requestCode);
return;
if (resultCode != RESULT_OK)
Toast.makeText(this, "Permission for screen recording is denied", Toast.LENGTH_LONG).show();
isRecording = false;
recordBtnReload();
return;
mediaProjectionCallback = new MediaProjection.Callback()
@Override
public void onStop()
if (isRecording)
isRecording = false;
recordBtnReload();
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
mediaProjection = null;
stopScreenSharing();
;
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
mediaProjection.registerCallback(mediaProjectionCallback, null);
virtualDisplay = createVirtualDisplay();
mediaRecorder.start();
isRecording = true;
recordBtnReload();
@Override
protected void onDestroy()
super.onDestroy();
destroyMediaProjection();
我不知道我做错了什么。我还在学习应用程序开发。
【问题讨论】:
您能否提供一个简化示例的完整代码?例如,您可以去掉适配器并只记录 getData() 的结果。目前,当我将您提供的代码复制到一个活动中时,它远非可运行。如果不先做很多工作,我就帮不了你,这会降低你得到答案的可能性。查看***.com/help/minimal-reproducible-example @Michiyo 我在我的问题中编辑了我的代码。现在,它只有 mediarecorder 功能并将录制的视频保存到存储中。如果您将代码复制到活动中并在清单中添加相关权限,则应用程序应该会运行。请检查您的文件目录以获取录制的文件。您会注意到即使您录制了多次,也只会创建一个文件。我必须终止该应用程序并重新启动才能创建新的录制文件。 【参考方案1】:我的代码中的问题在于 initRecorder() 函数。而不是使用以下代码来创建文件名:
String videoName = ("Video_" + todayDate + ".mp4");
其中,todayDate 是一个日期格式化程序。我用以下代码替换了代码:
String videoName = ("Video_" + System.currentTimeMillis() + ".mp4");
这需要当前系统时间并在文件名中分配它。现在新文件已创建,我不必每次都重新启动应用程序来记录新文件。
【讨论】:
以上是关于MediaRecorder 没有第二次录制的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MediaRecorder 获取录制声音的每个频率?