我正在开发一个可以记录 Android 设备屏幕内容并将其显示在 SurfaceView 上的应用程序。到目前为止,SurfaceView 是屏幕中间的一个框,当前正在显示整个屏幕的内容,连同它自己,创建一个重复的图像。有没有办法重复隐藏SurfaceView,创建一个虚拟显示,然后用虚拟显示的内容显示SurfaceView?
RecordingSession.java
class RecordingSession
implements MediaScannerConnection.OnScanCompletedListener {
static final int VIRT_DISPLAY_FLAGS=
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
private RecordingConfig config;
private final File output;
private final Context ctxt;
private final ToneGenerator beeper;
private MediaRecorder recorder;
private MediaProjection projection;
private VirtualDisplay vdisplay;
private Window window;
RecordingSession(Context ctxt, RecordingConfig config,
MediaProjection projection, Window window) {
this.ctxt=ctxt.getApplicationContext();
this.window = window;
this.config=config;
this.projection=projection;
this.beeper=new ToneGenerator(
AudioManager.STREAM_NOTIFICATION, 100);
output=new File(ctxt.getExternalFilesDir(null), "andcorder.mp4");
output.getParentFile().mkdirs();
}
void start() {
//this.window.close();
vdisplay=projection.createVirtualDisplay("andcorder",
config.width, config.height, config.density,
VIRT_DISPLAY_FLAGS, this.window.getScreenShot().getHolder().getSurface(), null, null);
//this.window.open();
beeper.startTone(ToneGenerator.TONE_PROP_ACK);
}
void stop() {
projection.stop();
vdisplay.release();
}
@Override
public void onScanCompleted(String path, Uri uri) {
beeper.startTone(ToneGenerator.TONE_PROP_NACK);
}
}
窗口.java
public class Window {
// declaring required variables
private Context context;
private View mView;
private WindowManager.LayoutParams mParams;
private WindowManager mWindowManager;
private LayoutInflater layoutInflater;
public SurfaceView getScreenShot() {
return screenShot;
}
private SurfaceView screenShot;
private LinearLayout toDisplay;
public Window(Context context){
this.context=context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// set the layout parameters of the window
mParams = new WindowManager.LayoutParams(
// Shrink the window to wrap the content rather
// than filling the screen
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
// Display it on top of other application windows
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
// Don't let it grab the input focus
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
// Make the underlying application window visible
// through any transparent parts
PixelFormat.TRANSLUCENT);
}
// getting a LayoutInflater
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// inflating the view with the custom layout we created
mView = layoutInflater.inflate(R.layout.popup_window, null);
screenShot= mView.findViewById(R.id.screenShot);
// Define the position of the
// window within the screen
mParams.gravity = Gravity.CENTER;
mWindowManager = (WindowManager)context.getSystemService(WINDOW_SERVICE);
}
public void open() {
try {
// check if the view is already
// inflated or present in the window
if(mView.getWindowToken()==null) {
if(mView.getParent()==null) {
mWindowManager.addView(mView, mParams);
}
}
} catch (Exception e) {
Log.d("Error1",e.toString());
}
}
public void hide() {
try {
mView.setVisibility(View.INVISIBLE);
} catch (Exception e) {
Log.d("Error3",e.toString());
}
}
public void show() {
try {
mView.setVisibility(View.VISIBLE);
} catch (Exception e) {
Log.d("Error4",e.toString());
}
}
public void close() {
try {
// remove the view from the window
((WindowManager)context.getSystemService(WINDOW_SERVICE)).removeView(mView);
// invalidate the view
mView.invalidate();
// remove all views
((ViewGroup)mView.getParent()).removeAllViews();
// the above steps are necessary when you are adding and removing
// the view simultaneously, it might give some exceptions
} catch (Exception e) {
Log.d("Error2",e.toString());
}
}
}
popup_window.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="4dp"
android:background="@null">
<SurfaceView
android:id="@+id/screenShot"
android:layout_width="match_parent"
android:layout_height="250dp" />
</RelativeLayout>