Mar*_*k H 13 macos cocoa screen-recording macos-catalina
检测用户是否已启用此API的可靠方法是什么?
CGWindowListCreateImage即使禁用了屏幕录制API,也将返回有效对象。可能有多种组合(kCGWindowListOptionIncludingWindow,kCGWindowListOptionOnScreenBelowWindow),只有一些组合会返回NULL。
- (CGImageRef)createScreenshotImage
{
NSWindow *window = [[self view] window];
NSRect rect = [window frame];
rect.origin.y = NSHeight([[window screen] frame]) - NSMaxY([window frame]);
CGImageRef screenshot = CGWindowListCreateImage(
rect,
kCGWindowListOptionIncludingWindow,
//kCGWindowListOptionOnScreenBelowWindow,
0,//(CGWindowID)[window windowNumber],
kCGWindowImageBoundsIgnoreFraming);//kCGWindowImageDefault
return screenshot;
}
Run Code Online (Sandbox Code Playgroud)
唯一可靠的方法是CGDisplayStreamCreate冒险,因为Apple每年都会更改隐私设置。
- (BOOL)canRecordScreen
{
if (@available(macOS 10.15, *)) {
CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
;
});
BOOL canRecord = stream != NULL;
if (stream) {
CFRelease(stream);
}
return canRecord;
} else {
return YES;
}
}
Run Code Online (Sandbox Code Playgroud)
cho*_*rry 10
这里介绍的所有解决方案都以一种或另一种方式存在缺陷。问题的根源在于,您了解窗口的权限(通过窗口列表中的名称)与您了解窗口的进程所有者(例如WindowServer和Dock)之间没有关联。您查看屏幕上像素的权限是两组稀疏信息的组合。
这是一种启发式方法,涵盖了macOS 10.15.1以来的所有情况:
BOOL canRecordScreen = YES;
if (@available(macOS 10.15, *)) {
canRecordScreen = NO;
NSRunningApplication *runningApplication = NSRunningApplication.currentApplication;
NSNumber *ourProcessIdentifier = [NSNumber numberWithInteger:runningApplication.processIdentifier];
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSUInteger numberOfWindows = CFArrayGetCount(windowList);
for (int index = 0; index < numberOfWindows; index++) {
// get information for each window
NSDictionary *windowInfo = (NSDictionary *)CFArrayGetValueAtIndex(windowList, index);
NSString *windowName = windowInfo[(id)kCGWindowName];
NSNumber *processIdentifier = windowInfo[(id)kCGWindowOwnerPID];
// don't check windows owned by this process
if (! [processIdentifier isEqual:ourProcessIdentifier]) {
// get process information for each window
pid_t pid = processIdentifier.intValue;
NSRunningApplication *windowRunningApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
if (! windowRunningApplication) {
// ignore processes we don't have access to, such as WindowServer, which manages the windows named "Menubar" and "Backstop Menubar"
}
else {
NSString *windowExecutableName = windowRunningApplication.executableURL.lastPathComponent;
if (windowName) {
if ([windowExecutableName isEqual:@"Dock"]) {
// ignore the Dock, which provides the desktop picture
}
else {
canRecordScreen = YES;
break;
}
}
}
}
}
CFRelease(windowList);
}
Run Code Online (Sandbox Code Playgroud)
If canRecordScreen is not set, you'll need to put up some kind of dialog that warns the user that they'll only be able to see the menubar, desktop picture, and the app's own windows. Here's how we presented it in our app xScope.
And yes, I'm still bitter that these protections were introduced with little regard to usability.
小智 10
Apple 提供直接的低级 API 来检查访问和授予访问权限。无需使用棘手的解决方法。
/* Checks whether the current process already has screen capture access */
@available(macOS 10.15, *)
public func CGPreflightScreenCaptureAccess() -> Bool
Run Code Online (Sandbox Code Playgroud)
使用上述功能检查屏幕截图访问。
如果未授予访问权限,请使用以下功能提示访问权限
/* Requests event listening access if absent, potentially prompting */
@available(macOS 10.15, *)
public func CGRequestScreenCaptureAccess() -> Bool
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3491 次 |
| 最近记录: |