我正在将此代码用于Nexus 5上运行6.0.1的7月安全更新的屏幕录制。屏幕录制在运行5.0.1,6.0,6.0.1的其他设备上工作正常,但是它在我的手机上不起作用。当我尝试开始屏幕录制时,它会给我以下错误。
E/MediaRecorder: SurfaceMediaSource could not be initialized!
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1995, result=-1, data=Intent { (has extras) }} to activity {MainActivity}: java.lang.IllegalStateException: failed to get surface
at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
Caused by: java.lang.IllegalStateException: failed to get surface
at android.media.MediaRecorder.getSurface(Native Method)
它无法获得屏幕录制的表面。这是什么原因造成的,我该如何解决?
源代码:
public static MediaProjectionManager getmMediaProjectionManager(final MainActivity context) {
DisplayMetrics metrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
DISPLAY_HEIGHT = metrics.heightPixels;
DISPLAY_WIDTH = metrics.widthPixels;
mMediaRecorder = new MediaRecorder();
mMediaProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
return mMediaProjectionManager;
}
@TargetApi(21)
public static void startScreenRecording(Intent data) {
mMediaProjectionCallback = new MediaProjectionCallback();
initRecorder(null);
mMediaProjection = mMediaProjectionManager.getMediaProjection(RESULT_OK, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
@TargetApi(21)
private static VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("MainActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
@TargetApi(21)
private static void initRecorder(MainActivity context) {
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(Environment
.getExternalStorageDirectory() + "/video"+ System.currentTimeMillis()+".mp4");
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(VIDEO_ENCODING_BITRATE);
mMediaRecorder.setVideoFrameRate(VIDEO_FRAME_RATE);
mMediaRecorder.prepare();
} catch (Exception e) {
Log.e("Util", e.getLocalizedMessage());
}
}
@TargetApi(21)
private static class MediaProjectionCallback extends MediaProjection.Callback {
@Override
public void onStop() {
}
}
@TargetApi(21)
public static void stopScreenSharing() {
mMediaRecorder.stop();
mMediaRecorder.reset();
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
destroyMediaProjection();
}
@TargetApi(21)
private static void destroyMediaProjection() {
if (mMediaProjection != null) {
Log.e(TAG, "destroying projection");
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
}
此致敬意
这个代码会工作的!!
package com.example.signeyweb.TestingPackage;
import static android.content.ContentValues.TAG;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.signeyweb.R;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestingTwoActivity extends AppCompatActivity {
private static final int CAST_PERMISSION_CODE = 22;
public DisplayMetrics mDisplayMetrics = new DisplayMetrics();
public MediaProjection mMediaProjection;
public VirtualDisplay mVirtualDisplay;
public MediaRecorder mMediaRecorder;
MediaProjectionManager mProjectionManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testing_two);
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mDisplayMetrics = getApplicationContext().getResources().getDisplayMetrics();
prepareRecording();
}
private void startRecording() {
// If mMediaProjection is null that means we didn't get a context, lets ask the user
if (mMediaProjection == null) {
// This asks for user permissions to capture the screen
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), CAST_PERMISSION_CODE);
return;
}
mVirtualDisplay = getVirtualDisplay();
mMediaRecorder.start();
}
private void stopRecording() {
if (mMediaRecorder != null) {
mMediaRecorder.stop();
mMediaRecorder.reset();
}
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
}
if (mMediaProjection != null) {
mMediaProjection.stop();
}
prepareRecording();
}
public String getCurSysDate() {
return new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date());
}
private void prepareRecording() {
final String directory = Environment.getExternalStorageDirectory() + File.separator + "Recordings";
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Toast.makeText(this, "Failed to get External Storage", Toast.LENGTH_SHORT).show();
return;
}
final File folder = new File(directory);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
String filePath;
if (success) {
String videoName = ("capture_" + getCurSysDate() + ".mp4");
filePath = directory + File.separator + videoName;
} else {
Toast.makeText(this, "Failed to create Recordings directory", Toast.LENGTH_SHORT).show();
return;
}
int width = mDisplayMetrics.widthPixels;
int height = mDisplayMetrics.heightPixels;
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(width, height);
mMediaRecorder.setOutputFile(filePath);
try {
mMediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != CAST_PERMISSION_CODE) {
// Where did we get this request from ? -_-
Log.w(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this, "Screen Cast Permission Denied :(", Toast.LENGTH_SHORT).show();
return;
}
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
// TODO Register a callback that will listen onStop and release & prepare the recorder for next recording
// mMediaProjection.registerCallback(callback, null);
mVirtualDisplay = getVirtualDisplay();
mMediaRecorder.start();
}
private VirtualDisplay getVirtualDisplay() {
int screenDensity = mDisplayMetrics.densityDpi;
int width = mDisplayMetrics.widthPixels;
int height = mDisplayMetrics.heightPixels;
return mMediaProjection.createVirtualDisplay(this.getClass().getSimpleName(),
width, height, screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
}
public void startrecording(View view) {
startRecording();
}
public void stoprecordingg(View view) {
stopRecording();
}
}
我尝试了上面的所有答案,但我仍然得到同样的错误。经过一个下午的调试,我得到了原因,如果你在上面的这些答案中也没有得到解决方案。然后你可以试试我的解决方案。我发现当我将DISPLAY_WIDTH替换为较小的数字时,例如1024,那么它就起作用了。这是我的代码:
mediaRecorder.setVideoSize(2048, 1024);
这与这个问题基本相同。我也面临着这个问题。奇怪的是,它只在Marshmallow上发生,在Lollipop上确实有效。
文件说:
表面获取表面 ()
只能在准备后才能打电话。在开始之前渲染到表面的帧将被丢弃。抛出:
非法状态异常 - 如果在准备之前、停止之后调用它,或者在视频源未设置为 SURFACE 时调用它。
但在Mediarecorder中。java,它是:
如果在{@link #prepare}之后和{@link #stop}之前调用,@将引发IllegalStateException。
但是,无论我把它放在preset()
之前还是之后都没有区别,两者都不起作用。奇怪的是,它抛出了一个非法状态异常,
尽管上述所有事情都不适用。
但是,马特·斯奈德的这个解决方案确实适用于Marshmallow。但是,由于IMO更加困难(尤其是在尝试录制音频时),因此最好也能与MediaRecorder一
起运行它。
如果有人想重现问题,只需使用这个或这个代码,并在Marshmallow机器上运行它。
问题内容: 例如我有一个功能: 我怎样才能返回AJAX后得到的? 问题答案: 因为请求是异步的,所以您无法返回ajax请求的结果(而同步ajax请求是一个 糟糕的 主意)。 最好的选择是将自己的回调传递给f1 然后,您将像这样致电:
我有两个活动和两个布局。当我在第一个活动中显示列表时,一切都正常,并在单击时给出列表中项目的编号,但当我尝试在第二个活动中重复相同的内容时,它会告诉我RecycleServiceClickListener侦听器为空。 适配器: 第一项活动: 第二项活动: 错误: 我不明白为什么在第一种情况下,它正常处理单击,而在第二种情况下,它说RecyclerViewClickListener为null
问题内容: 我在使用Ajax时遇到问题。 问题是,在获得ajax响应之前,它会返回cnt。因此它总是返回NULL。 有没有办法使正确的返回响应值? 谢谢! 问题答案: 由于AJAX请求是异步的,因此您的cnt变量将在请求返回并调用成功处理程序之前返回。 我建议重构您的代码以解决此问题。 一种方法是从AJAX请求的成功处理程序中调用调用了GetGrantAmazonItemCnt()的任何函数,此方
我想在下面返回JSON。 {“名字”:“杰基”} 新来的春靴在这里。1天大。有没有合适的方法可以做到这一点?
加载样式表,并在用户单击按钮时将其应用于场景 调用getScene()返回null。 函数所在的类是场景的控制器和根节点,我使用SceneBuilder 2.0,并将类设置为加载fxml的控制器,它是一个。 问题代码是类中的一个成员函数,标记是这样的,我可以通过设置按钮来调用它。 完整的代码可以在https://github.com/SebastianTroy/FactorioManufactur
问题内容: 我创建了一个自定义错误类型来包装错误,以便更轻松地在Golang中进行调试。当有打印错误时它可以工作,但是现在引起了恐慌。 演示版 当我调用一个函数时,它不会返回错误,我仍然应该能够包装该错误。 预期的行为是,如果错误为nil,则应该简单地忽略它,不幸的是,它会做相反的事情。 我希望它能打印出来。而是即使错误为nil也会打印。 问题答案: 正在将err变量与nil进行比较,但实际上它是