# android录屏并上传

流程思路是:

(1)利用系统录屏API MediaProjectionManager 向用户询问是否录制

(2)返回一个 Intent data 对象,根据这个对象调用 MediaProjectionManager.getMediaProjection() 方法生成 MediaProjection 对象

(3)根据 MediaProjection 对象创建 VirtualDisplay 实例

(4)创建 MediaRecorder 对象并初始化

(5)调用 MediaRecorder.start() 开始录制

(6)调用 MediaRecorder.stop() 停止录制

(7)上传文件

调用 okhttp3 库

安装 implementation "com.squareup.okhttp3:okhttp:4.9.3"

MyMediaRecorder.java:

public class MyMediaRecorder {
    private static String TAG = "MyMediaRecorder";
    public static final int RECORD_REQUEST_CODE = 0x34;
    private MediaProjectionManager mMediaProjectionManager;
    private MediaRecorder mediaRecorder;
    private Context _c;
    private MainActivity _m;
    private String videoName = "/sdcard/tempRecorder.mp4"; // 录制文件地址
    public Bundle saveIntent = null; // 保存用户确认信息

    public MyMediaRecorder(Context context, MainActivity mainActivity) {
        _c = context;
        _m = mainActivity;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mMediaProjectionManager = (MediaProjectionManager) _c.getSystemService(_c.MEDIA_PROJECTION_SERVICE); // 创建录屏实例
        }
    }

        // 启动录制
    public void startRecorder() {
        if(saveIntent == null) {
            Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent(); // 创建录屏请求
            _m.startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
        } else { // 如果保存了上一次确认的信息则可以直接录屏
            Intent data = new Intent();
            data.putExtras(saveIntent);
            getMediaProjection(data); // 开始录制
        }
    }

    // 停止录制
    public void endRecorder() {
        if(mediaRecorder != null){
            mediaRecorder.stop();
            mediaRecorder.reset();
        }
        if(virtualDisplay != null) {
            virtualDisplay.release();
        }
        try {
            String url = ""; // 接口地址
            String perams = ""; // 接口参数
            String auth = ""; // Authentication 校验
            uploadFile(url, videoName, perams, auth); // 文件上传
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    // 弹框回调(该方法是 MainActivity onActivityResult 的回调)
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode == Activity.RESULT_OK) {
            saveIntent = data.getExtras(); // 保存用户的确认信息
            getMediaProjection(data); // 开始录制
        }
    }

    // 开始录制
    private void getMediaProjection(Intent data) {
        MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, data);
        if(mediaProjection == null) {
            Log.w(TAG,"程序发生错误");
            return;
        }
        DisplayMetrics metrics = new DisplayMetrics();
        _m.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        createVirtualDisplay(metrics, mediaProjection); // 创建 VirtualDisplay
        int orientation = _m.getResources().getConfiguration().orientation;
        initRecorder(metrics, orientation); // 初始化录屏
        mediaRecorder.start(); // 开始录制
    }

    VirtualDisplay virtualDisplay = null;
    private void createVirtualDisplay(DisplayMetrics displayMetrics, MediaProjection mediaProjection) {
        // 如果当前屏幕 尺寸 大于 XHIGH  则统一使用 720 * 1280 ,其他就使用本身屏幕的大小
        virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen",
                displayMetrics.widthPixels, displayMetrics.heightPixels, displayMetrics.densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
    }

    // 初始化录制
    private void initRecorder(DisplayMetrics displayMetrics, int orientation) {
        mediaRecorder = new MediaRecorder();
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        int dpi = displayMetrics.densityDpi;
        // 视频最大的尺寸 720 * 1280 ,其他视频尺寸使用屏幕大小
        if (dpi > DisplayMetrics.DENSITY_XHIGH) {
            width = (orientation == Configuration.ORIENTATION_LANDSCAPE ? 1280 : 720);
            height = (orientation == Configuration.ORIENTATION_LANDSCAPE ? 720 : 1280);
        }
        //如果是横屏,视频输出时旋转90度
        mediaRecorder.setOrientationHint(orientation != Configuration.ORIENTATION_LANDSCAPE ? 0 : 90);
        //  音频源,这里需要 android.permission.RECORD_AUDIO 权限
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        //  视频来源
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        //  视频输出格式
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        // 录制输出文件
        mediaRecorder.setOutputFile(videoName);
        //视频编码格式
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        //音频编码格式
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        // 设置最大时长5分钟
        mediaRecorder.setMaxDuration(5 * 60 * 1000);
        //  设置视频文件的比特率,经过测试该属性对于视频大小影响最大
        mediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);
        //设置视频分辨率
        mediaRecorder.setVideoSize(width, height);
        //设置视频帧频率
        mediaRecorder.setVideoFrameRate(30);

        // 录制发生错误的监听
        mediaRecorder.setOnErrorListener((mr, what, extra) -> {

        });
        //记录录制时出现的信息事件
        mediaRecorder.setOnInfoListener((mr, what, extra) -> {

        });
        try {
            //准备录制
            mediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 文件上传
    private void uploadFile(String url, String filePath, String perams, String auth) {
        MediaType types = MediaType.get("video/mp4");
        String fileName = "record-screen-" + System.currentTimeMillis() + ".mp4";
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("perams", perams)
                .addFormDataPart("file", fileName, RequestBody.create(new File(filePath),types))
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .header("Authentication", auth)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                Log.i(TAG,response.body().string());
                Log.i(TAG,"上传失败");
                Log.i(TAG,"code:" + response.code());
            } else {
                Log.i(TAG,"上传成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

MainActivity.java:

MyMediaRecorder myMediaRecorder;
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
    myMediaRecorder = new MyMediaRecorder(this, MainActivity.this);
    myMediaRecorder.startRecorder(); // 启动录制
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == MyMediaRecorder.RECORD_REQUEST_CODE) { // 处理录屏回调
        myMediaRecorder.onActivityResult(requestCode, resultCode, data);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上次更新: 3/9/2022, 6:56:39 PM