public class ScreenRecordService extends Service {
private MediaProjection mediaProjection;
private MediaRecorder mediaRecorder;
private VirtualDisplay virtualDisplay;
private int width;
private int height;
private int dpi;
private boolean running;
private String videoPath = "";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
public class ScreenRecordBinder extends Binder {
public ScreenRecordService getScreenRecordService() {
return ScreenRecordService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ScreenRecordBinder();
}
public void setMediaProjection(MediaProjection projection) {
mediaProjection = projection;
}
public void setConfig(int width, int height, int dpi) {
this.width = width;
this.height = height;
this.dpi = dpi;
}
public boolean isRunning() {
return running;
}
public boolean startRecord() {
if (mediaProjection == null || running) {
return false;
}
initRecorder();
createVirtualDisplay();
try{
mediaRecorder.start();
running = true;
return true;
}catch (Exception e){
e.printStackTrace();
Toast.makeText(this,"开启失败,没有开始录屏",Toast.LENGTH_SHORT).show();
running = false;
return false;
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public boolean stopRecord() {
if (!running) {
return false;
}
running = false;
try{
mediaRecorder.stop();
mediaRecorder.reset();
virtualDisplay.release();
}catch (Exception e){
e.printStackTrace();
Toast.makeText(this,"录屏出现异常,视频保存失败!",Toast.LENGTH_SHORT).show();
return false;
}
Toast.makeText(this,"录屏结束,保存成功!",Toast.LENGTH_SHORT).show();
return true;
}
public void initRecorder() {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
videoPath = getSaveDirectory() + System.currentTimeMillis() + ".mp4";
mediaRecorder.setOutputFile(videoPath);
mediaRecorder.setVideoSize(width, height);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncodingBitRate(2 * 1920 * 1080);
mediaRecorder.setVideoFrameRate(18);
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this,
"Recorder录像机prepare失败,无法使用,请重新初始化!",
Toast.LENGTH_SHORT).show();
}
}
public void createVirtualDisplay() {
try {
virtualDisplay = mediaProjection.createVirtualDisplay("VirtualScreen", width, height, dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
}catch (Exception e){
e.printStackTrace();
Toast.makeText(this,"virtualDisplay创建录屏异常,请退出重试!",Toast.LENGTH_SHORT).show();
}
}
public String getSaveDirectory() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String rootDir = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/" + "录屏文件" + "/";
Log.d("", "getSaveDirectory: "+rootDir);
File file = new File(rootDir);
if (!file.exists()) {
if (!file.mkdirs()) {
return null;
}
}
return rootDir;
} else {
return null;
}
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private final static int REQUEST_CODE = 101;
private final static int PERMISSION_REQUEST_CODE = 1101;
MediaProjectionManager mediaProjectionManager;
MediaProjection mediaProjection;
Button btn_start_recorder;
Button btn_stop_recorder;
DisplayMetrics metrics;
ScreenRecordService screenRecordService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_start_recorder = findViewById(R.id.btn_start_recorder);
btn_stop_recorder = findViewById(R.id.btn_stop_recorder);
btn_start_recorder.setOnClickListener(this);
btn_stop_recorder.setOnClickListener(this);
}
public void checkPermission() {
if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)){
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO},PERMISSION_REQUEST_CODE);
}else{
connectService();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == PERMISSION_REQUEST_CODE){
if(grantResults.length > 0 &&
(grantResults[0] != PackageManager.PERMISSION_GRANTED ||
grantResults[1] != PackageManager.PERMISSION_GRANTED)){
Toast.makeText(MainActivity.this,"请同意必须的应用权限,否则无法正常使用该功能!", Toast.LENGTH_SHORT).show();
}else if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
grantResults[1] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(MainActivity.this,"权限申请成功,用户同意!",Toast.LENGTH_SHORT).show();
connectService();
}
}
}
public void connectService(){
Intent intent = new Intent(this,ScreenRecordService.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
ScreenRecordService.ScreenRecordBinder binder = (ScreenRecordService.ScreenRecordBinder) iBinder;
screenRecordService = binder.getScreenRecordService();
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent,REQUEST_CODE);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(MainActivity.this,"录屏服务未连接成功,请重试!",Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE && resultCode == RESULT_OK){
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode,data);
if(screenRecordService != null){
screenRecordService.setMediaProjection(mediaProjection);
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
screenRecordService.setConfig(metrics.widthPixels,metrics.heightPixels,metrics.densityDpi);
}
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_start_recorder:
checkPermission();
if(screenRecordService != null && screenRecordService.isRunning()){
Toast.makeText(MainActivity.this,"当前正在录屏,请不要重复点击哦!",Toast.LENGTH_SHORT).show();
} else if(screenRecordService != null && !screenRecordService.isRunning()){
screenRecordService.startRecord();
setToBackground();
} else if(screenRecordService == null){
connectService();
}
break;
case R.id.btn_stop_recorder:
if(screenRecordService != null && !screenRecordService.isRunning()){
Toast.makeText(MainActivity.this,"您还没有录屏,无法停止,请先开始录屏吧!",Toast.LENGTH_SHORT).show();
}else if(screenRecordService != null && screenRecordService.isRunning()){
screenRecordService.stopRecord();
}
break;
}
}
private void setToBackground(){
Intent home = new Intent(Intent.ACTION_MAIN);
home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
home.addCategory(Intent.CATEGORY_HOME);
startActivity(home);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_start_recorder"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_marginTop="200dp"
android:text="Start Recorder"
android:textSize="25dp" />
<Button
android:id="@+id/btn_stop_recorder"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:text="Stop Recorder"
android:textSize="25dp" />
</LinearLayout>