标签: android-mediaprojection

如何在全球范围内正确截取屏幕截图?

背景

从Android API 21开始,应用程序可以全局截取屏幕并记录屏幕.

问题

我已经在互联网上发现了一些示例代码,但它有一些问题:

  1. 这很慢.也许有可能避免它,至少对于多个​​屏幕截图,避免通知它被删除直到真的不需要.
  2. 它左右有黑色边距,这意味着计算可能出错:

在此输入图像描述

我试过的

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)

android screenshot android-mediaprojection

15
推荐指数
1
解决办法
2846
查看次数

流Android屏幕

我试图让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)

java android android-mediarecorder android-mediaprojection

14
推荐指数
1
解决办法
2671
查看次数

android mediaprojection截图包含黑框

我正在使用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)

问题是捕获的图像包含如下图像的黑框.

在此输入图像描述

编辑

上述问题可以通过位图操作来解决.

不过,我现在正在寻找可以应用到解决方案MediaProjectionSurfaceViewImageReader实现设备记录.

android android-mediarecorder android-mediaprojection

11
推荐指数
3
解决办法
1778
查看次数

android Q 中无法识别 MediaProjection 服务类型

随着 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)

android android-mediaprojection android-10.0

10
推荐指数
1
解决办法
9247
查看次数

服务中的Android MediaProjectionManager

我想构建一个应用程序,我必须在服务中使用MediaProjectionManager.但我无法解决它,因为'startActivityForResult'不能在Service类中使用.

service android broadcastreceiver android-mediaprojection

8
推荐指数
1
解决办法
7075
查看次数

Android ImageReader获得NV21格式?

我没有成像或图形的背景,所以请耐心等我:)

我在我的一个项目中使用JavaCV.在这些例子中,Frame构造了一个具有一定大小的缓冲区的a .

public void onPreviewFrame(byte[] data, Camera camera)在Android中使用该函数时,data如果将声明声明Framenew Frame(frameWidth, frameHeight, Frame.DEPTH_UBYTE, 2);where frameWidthframeHeight声明为,则复制此字节数组没有问题

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)

android imaging image android-mediaprojection

8
推荐指数
1
解决办法
7966
查看次数

MediaProjection:如何将安全层视为不可见而不是黑色?

好吧,我的目标是使用捕获设备屏幕的所有内容MediaProjection,但不捕获覆盖。然后在网上搜索这个问题,我在这里看到了两个问题,其中一个说这是不可能的,另一个建议用“安全”标志定义覆盖并将其视为不可见而不是黑色。第二个问题给了我一个希望,我想知道如何在注释中显示使用android代码(Java)而不是C ++进行显示的方法,或者通过其他方法做到这一点?

java android android-mediaprojection

8
推荐指数
0
解决办法
175
查看次数

媒体投影在 Android Pie 和 Q 中需要 ServiceInfo.FOREGROUND_SERVICE TYPE_MEDIA_PROJECTION 类型的前台服务

任何机构都知道为什么会发生此错误,即使我在调用 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

8
推荐指数
1
解决办法
1万
查看次数

使 FLAG_SECURE 窗口在 Android 屏幕截图中不可见

我有一个带有标志 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 之外?

android android-windowmanager android-mediaprojection

7
推荐指数
0
解决办法
947
查看次数

如何仅使用一次而不是每次使用 MediaProjectionManager 屏幕捕获权限?

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)

android android-mediaprojection

7
推荐指数
1
解决办法
6015
查看次数