前言
Android提供了MediaProjection来实现录屏,通过MediaProjection可以获取当前屏幕的视频流,而视频流需要通过编解码来压缩进行传输,通过MediaCodec可实现视频的编码和解码。视频流的推送和接收可通过Socket或WebSocket来实现,服务端推送编码的视频流,客户端接收视频流并进行解码,然后渲染在SurfaceView上即可显示服务端的画面。
媒体投影MediaProjection的核心是虚拟屏幕,您可以通过对 MediaProjection 实例调用 createVirtualDisplay() 来创建虚拟屏幕(VirtualDisplay):
Android的媒体投影MediaProjection介绍:媒体投影
投屏服务端的实现
服务端主入口负责请求录屏和启动录屏服务,服务端主入口的实现如下:
package com.example.screenprojection;
import android.content.Intent;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private static final int PROJECTION_REQUEST_CODE = 1;
private MediaProjectionManager mediaProjectionManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
}
public void onClick(View view) {
if (view.getId() == R.id.btn_start) {
startProjection();
}
}
// 请求开始录屏
private void startProjection() {
Intent intent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(intent, PROJECTION_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
if (requestCode == PROJECTION_REQUEST_CODE) {
Intent service = new Intent(this, ScreenService.class);
service.putExtra("code", resultCode);
service.putExtra("data", data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(service);
} else {
startService(service);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
Android8.0后录屏需要开启前台服务通知,录屏服务开启后同时启动WebSocketServer服务端,前台服务代码如下:
package com.example.screenprojection;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.IBinder;
public class ScreenService extends Service {
private MediaProjectionManager mMediaProjectionManager;
private SocketManager mSocketManager;
@Override
public void onCreate() {
super.onCreate();
mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
createNotificationChannel();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int resultCode = intent.getIntExtra("code", -1);
Intent resultData = intent.getParcelableExtra("data");
startProject(resultCode, resultData);
return super.onStartCommand(intent, flags, startId);
}
// 录屏开始后进行编码推流
private void startProject(int resultCode, Intent data) {
MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
if (mediaProjection == null) {
return;
}
// 初始化服务器端
mSocketManager = new SocketManager();
mSocketManager.start(mediaProjection);
}
private void createNotificationChannel() {
Notification.Builder builder = new Notification.Builder(this.getApplicationContext());
Intent nfIntent = new Intent(this, MainActivity.class);
builder
.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
.setLargeIcon(
BitmapFactory.decodeResource(
this.getResources(), R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标)
.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
.setContentText("is running......") // 设置上下文内容
.setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES

本文详细介绍了如何使用Android的MediaProjection API实现屏幕录制,并结合WebSocket服务进行实时传输。服务端通过MediaProjection捕获屏幕,编码为H.265视频流,然后通过WebSocket推送给客户端。客户端接收视频流并解码后在SurfaceView上显示。过程中涉及到了MediaProjectionManager、MediaCodec、WebSocketServer和SocketManager等关键组件。服务端和客户端都需要处理权限配置、网络连接和异常处理等问题。
最低0.47元/天 解锁文章
1011

被折叠的 条评论
为什么被折叠?



