是否可以从同一活动中录制当前运行活动的屏幕视频?
我知道如何截取当前活动的截图,但对屏幕视频记录没有任何想法。
我该如何开始呢?我不知道如何开始它。
答案 0 :(得分:25)
自从棒棒糖以来我们可以使用Media Projection API! (API 21 +)
以下是我用于录制的代码,请注意,我们首先需要获取用户的权限;)
private static final int CAST_PERMISSION_CODE = 22;
private DisplayMetrics mDisplayMetrics;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaRecorder mMediaRecorder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
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 = createVirtualDisplay();
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() {
try {
mMediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return;
}
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);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent 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() {
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*/);
}
这不是最终的代码,而是开始的良好基础:)
答案 1 :(得分:15)
编辑:这个答案取代了Danpe的答案below。
以编程方式记录您应用内的视频需要root访问权限。您会注意到Play商店中可用的应用程序在其应用程序描述中突出显示“需要根”。您还会注意到,这种方法可能还有一些特定的硬件要求(“不适用于Galaxy Nexus或Tegra 2/3 ......” - 来自Screencast Video Recorder应用程序的说明。
我自己从未编写过这段代码,但我已经对所需的方法提出了非常高级的想法。从post开始,您必须通过“/ dev / graphics / fb0”访问帧缓冲区数据。帧缓冲区的访问模式是660,这意味着您需要root访问权限才能访问它。获得root访问权限后,您可以使用帧缓冲区数据来创建屏幕截图(此project可能适用于此任务),然后根据这些屏幕截图创建视频(请参阅另一个关于如何{{3}的问题})。
我使用过Screencast应用程序,它在三星Note上运行良好。我怀疑这是他们采取的基本方法。
答案 2 :(得分:11)
普通Android应用程序缺少捕获帧缓冲区的权限(具体而言,它们不是AID_GRAPHICS组的成员)。这是出于安全原因 - 否则他们可能会从软键盘中窃取密码等。因此,一般情况下,如果没有某种方式解决权限问题,您无法从Android应用程序捕获屏幕。
您可以或多或少地捕获应用程序当前占用的屏幕区域的快照,方法是遍历视图层次结构中的顶部视图,并使用View.draw(Canvas)将其绘制到位图中,但是这将是不记录状态栏,软键盘,OpenGL表面等。
如果你想做得比这更好,你需要使用外部工具。工具需要root或使用ADB接口,因为通过ADB接口启动的进程具有AID_GRAPHICS权限。使用后一种方法,非特权应用程序可以连接到特权服务器进行录制。
粗略的工具可以分为以下几类:
仅限root的帧缓冲录像机应用程序(例如Screencast)。这些记录直接来自/ dev / graphics / fb0设备,但仅适用于帧缓冲可读的设备(例如,不在Tegra 2 Nexus 7上)。
仅限根屏幕捕获记录器应用程序(例如SCR,Rec等)。它们通过SurfaceFlinger捕获屏幕,并在更广泛的设备上工作。
非根屏幕捕获记录器应用程序(例如,Recordable,Ascrecorder)。这些要求用户启用USB调试并在通过主机PC连接时启动守护程序。此后,在重启设备之前不需要主机PC。也可以录制音频。
ADB工具(例如Android 4.4上的内置屏幕录像机)。要求您通过USB连接,无法捕获音频。
几个月前,我对可用的应用程序进行了比较:
http://recordable.mobi/compare
为了完整性,还有USB工具(例如,Mobizen)通过USB流式传输屏幕(受低USB带宽限制,无法录制音频),有些设备也可以通过wifi传输屏幕,然后可以捕获一个单独的设备。
答案 3 :(得分:4)
这是一篇相当古老的帖子,但我希望这能帮助那些仍在寻找记录Android设备屏幕的人:
自Android 5.0起,有一个可用于屏幕录制的新API: MediaProjection MediaProjection授予捕获屏幕内容的能力,但不能捕获系统音频。它也不会捕获安全的屏幕内容。
在Matt Snider的页面上有一个很好的例子,说明如何使用API将屏幕实际记录到SD卡上的文件中:LINK
答案 4 :(得分:2)
您可以在adb运行时使用DDMS捕获屏幕并拥有帧缓冲区的权限:
点击此链接了解更多详情:
ALSO 检查这个链接可能会得到一些你需要的想法:
http://answers.oreilly.com/topic/951-how-to-capture-video-of-the-screen-on-android/
并检查此项目:
希望这有帮助。答案 5 :(得分:0)
我创建了一个library来为您处理。包括显示可自定义的通知,如果您不想显示通知,可以将其禁用。
它需要API 21>
以下是有关如何使用它的简单演示:(更多信息可以在该库的自述文件中找到):
首先,在您的Activity
中声明并初始化它:
public class MainActivity extends AppCompatActivity implements HBRecorderListener {
//Declare HBRecorder
HBRecorder hbRecorder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Init HBRecorder
hbRecorder = new HBRecorder(this, this);
}
然后,当您要开始录制时,可以致电:
private void startRecordingScreen() {
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent permissionIntent = mediaProjectionManager != null ? mediaProjectionManager.createScreenCaptureIntent() : null;
startActivityForResult(permissionIntent, SCREEN_RECORD_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SCREEN_RECORD_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
//It is important to call this before starting the recording
hbRecorder.onActivityResult(resultCode, data, this);
//Start screen recording
hbRecorder.startScreenRecording(data);
}
}
}
您可以通过以下方式停止录制:
hbRecorder.stopScreenRecording();
onCompleteListener
会告诉您文件的创建时间:
@Override
public void HBRecorderOnComplete() {
//This is called once the file was created
}
我还添加了一堆可以设置的参数,例如更改AudioBitrate
,AudioSamplingRate
等。
答案 6 :(得分:-1)
您也可以通过这种方式录制屏幕:http://www.youtube.com/watch?v=4K2UDfP4lN8&list=UU4fDGas-Vz1xruuUY4QbF0w&feature=c4-overview。
该视频标题为“如何捕获/录制没有Root的Android屏幕(Mobizen)”。
视频参考了Mobizen的使用:https://play.google.com/store/apps/details?id=com.rsupport.mvagent