从Android API 21开始,应用程序可以全局截取屏幕并记录屏幕.
我已经在互联网上发现了一些示例代码,但它有一些问题:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_ID = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.checkIfPossibleToRecordButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
ScreenshotManager.INSTANCE.requestScreenshotPermission(MainActivity.this, REQUEST_ID);
}
});
findViewById(R.id.takeScreenshotButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
ScreenshotManager.INSTANCE.takeScreenshot(MainActivity.this);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ID)
ScreenshotManager.INSTANCE.onActivityResult(resultCode, data);
}
}
Run Code Online (Sandbox Code Playgroud)
布局/ activity_main.xml中
<LinearLayout …Run Code Online (Sandbox Code Playgroud) 我试图让Truiton ScreenCapture示例,以便使用MediaProjection记录设备屏幕
保存录音时,它可以正常工作
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
String localFilePath = getLocalFilePath();
mMediaRecorder.setOutputFile(localFilePath);
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.prepare();
Run Code Online (Sandbox Code Playgroud)
然而,当改变使用FileDescriptor时,它不是
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
String hostname = "10.26.100.18";
int port = 2007;
Socket socket = new Socket(InetAddress.getByName(hostname), port);
ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.fromSocket(socket);
LocalServerSocket localServerSocket = new LocalServerSocket(fileDescriptor.getFileDescriptor());
mMediaRecorder.setOutputFile(localServerSocket.getFileDescriptor());
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.prepare();
Run Code Online (Sandbox Code Playgroud)
如果没有使用LocalServerSocket,那么mMediaRecorder.prepare()抛出异常,现在我正在使用它,在下面的方法中得到异常mMediaRecorder.getSurface()
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("MainActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
Run Code Online (Sandbox Code Playgroud)
例外
Caused by: java.lang.IllegalStateException: failed to get surface
at …Run Code Online (Sandbox Code Playgroud) 我正在使用MediaProjection录制我的屏幕,如下所示
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
imageReader = ImageReader.newInstance(displayWidth, displayHeight, ImageFormat.JPEG, 5);
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
DisplayMetrics metrics = getResources().getDisplayMetrics();
int density = metrics.densityDpi;
mediaProjection.createVirtualDisplay("test", displayWidth, displayHeight, density, flags,
imageReader.getSurface(), null, projectionHandler);
Image image = imageReader.acquireLatestImage();
byte[] data = getDataFromImage(image);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Run Code Online (Sandbox Code Playgroud)
问题是捕获的图像包含如下图像的黑框.
编辑
上述问题可以通过位图操作来解决.
不过,我现在正在寻找可以应用到解决方案MediaProjection或SurfaceView中ImageReader实现设备记录.
随着 Android Q 的新隐私更改生效,现在任何使用MediaProjectionapi 的应用程序都必须在清单下的服务标签中指定android:foregroundServiceType属性。
但最近,我注意到虽然我设置了,android:foregroundServiceType="mediaprojection"但还是抛出了一个安全异常。有人知道我做错了什么吗?
显现:
<service
android:name=".services.MediaProjectionService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="mediaProjection" />
Run Code Online (Sandbox Code Playgroud)
抛出异常:
java.lang.RuntimeException: Unable to start service com.package.app.services.MediaProjectionService@6d0fed2 with Intent { act=com.package.app.services.action.startrecording cmp=com.package.app/.services.MediaProjectionService(has extras) }: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4103)
at android.app.ActivityThread.access$1800(ActivityThread.java:219)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7343)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:933)
Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.os.Parcel.createException(Parcel.java:2071)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987) …Run Code Online (Sandbox Code Playgroud) 我想构建一个应用程序,我必须在服务中使用MediaProjectionManager.但我无法解决它,因为'startActivityForResult'不能在Service类中使用.
我没有成像或图形的背景,所以请耐心等我:)
我在我的一个项目中使用JavaCV.在这些例子中,Frame构造了一个具有一定大小的缓冲区的a .
public void onPreviewFrame(byte[] data, Camera camera)在Android中使用该函数时,data如果将声明声明Frame为new Frame(frameWidth, frameHeight, Frame.DEPTH_UBYTE, 2);where frameWidth并frameHeight声明为,则复制此字节数组没有问题
Camera.Size previewSize = cameraParam.getPreviewSize();
int frameWidth = previewSize.width;
int frameHeight = previewSize.height;
Run Code Online (Sandbox Code Playgroud)
最近,Android添加了一种捕获屏幕的方法.当然,我想抓住那些图像并将它们转换为Frames.我修改了Google的示例代码以使用ImageReader.
这ImageReader被构造为ImageReader.newInstance(DISPLAY_WIDTH, DISPLAY_HEIGHT, PixelFormat.RGBA_8888, 2);.所以目前它使用RGBA_8888像素格式.我使用以下代码将字节复制到Frame,实例化为new Frame(DISPLAY_WIDTH, DISPLAY_HEIGHT, Frame.DEPTH_UBYTE, 2);:
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
mImage.close();
((ByteBuffer) frame.image[0].position(0)).put(bytes); …Run Code Online (Sandbox Code Playgroud) 好吧,我的目标是使用捕获设备屏幕的所有内容MediaProjection,但不捕获覆盖。然后在网上搜索这个问题,我在这里看到了两个问题,其中一个说这是不可能的,另一个建议用“安全”标志定义覆盖并将其视为不可见而不是黑色。第二个问题给了我一个希望,我想知道如何在注释中显示使用android代码(Java)而不是C ++进行显示的方法,或者通过其他方法做到这一点?
任何机构都知道为什么会发生此错误,即使我在调用 startforeground() 方法后调用 getMediaProjection() 方法,媒体投影也需要在 getMediaProjection() 上使用 ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION 类型的前台服务..!
堆栈跟踪是:
Process: com.al1.screenrecorder, PID: 24641
java.lang.RuntimeException: Unable to start service com.al1.screenrecorder.service.DisplayRecorderService@9ef2101 with Intent { cmp=com.al1.screenrecorder/.service.DisplayRecorderService (has extras) }: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4661)
at android.app.ActivityThread.access$2900(ActivityThread.java:292)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8147)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.os.Parcel.createException(Parcel.java:2071)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987)
at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:231)
at android.media.projection.MediaProjection.<init>(MediaProjection.java:75)
at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:104) …Run Code Online (Sandbox Code Playgroud) java android foreground-service android-mediaprojection android-9.0-pie
我有一个带有标志 FLAG_SECURE 的浮动窗口。它已成功隐藏在我设置的屏幕截图和 MediaProjection 中。当我通过 MediaProjection 录制时,它显示为黑色矩形对象。我的浮动窗口中的所有内容都被涂黑了。
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_PHONE;
params.format = PixelFormat.TRANSPARENT;
params.flags = WindowManager.LayoutParams.FLAG_SECURE;
windowManager.addView(floatingView, params);
Run Code Online (Sandbox Code Playgroud)
我的问题是,是否可以隐藏这个浮动窗口?我的意思是不将其显示为黑色对象,而是在浮动窗口下捕获内容,以便它完全隐藏在 MediaProjection 之外?
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int REQUEST_CODE = 1234;
private int mScreenDensity;
private MediaProjectionManager mProjectionManager;
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private ToggleButton mToggleButton;
private MediaRecorder mMediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int REQUEST_PERMISSIONS = 10;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
@Override
public …Run Code Online (Sandbox Code Playgroud)