Quel est un moyen fiable de détecter si l'utilisateur a activé cette API?
CGWindowListCreateImage
renvoie un objet valide même si l'API d'enregistrement d'écran est désactivée. Il existe plusieurs combinaisons possibles (kCGWindowListOptionIncludingWindow
, kCGWindowListOptionOnScreenBelowWindow
) et seules certaines renverront 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;
}
Le seul moyen fiable consiste à utiliser CGDisplayStreamCreate
, ce qui est risqué car Apple modifie toujours les paramètres de confidentialité chaque année.
- (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;
}
}
La réponse la plus favorable n'est pas tout à fait juste, a-t-il laissé de côté, comme partager l'état.
nous pouvons trouver la réponse dans WWDC ( https://developer.Apple.com/videos/play/wwdc2019/701/?time=1007 )
Voici quelques extraits de WWDC: le nom de la fenêtre et l'état de partage ne sont pas disponibles, sauf si l'utilisateur a pré-approuvé l'application pour l'enregistrement d'écran. Et cela parce que certaines applications mettent des données sensibles telles que les noms de compte ou des URL de pages Web plus probables dans le nom de la fenêtre.
- (BOOL)ScreeningRecordPermissionCheck {
if (@available(macOS 10.15, *)) {
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSUInteger numberOfWindows = CFArrayGetCount(windowList);
NSUInteger numberOfWindowsWithInfoGet = 0;
for (int idx = 0; idx < numberOfWindows; idx++) {
NSDictionary *windowInfo = (NSDictionary *)CFArrayGetValueAtIndex(windowList, idx);
NSString *windowName = windowInfo[(id)kCGWindowName];
NSNumber* sharingType = windowInfo[(id)kCGWindowSharingState];
if (windowName || kCGWindowSharingNone != sharingType.intValue) {
numberOfWindowsWithInfoGet++;
} else {
NSNumber* pid = windowInfo[(id)kCGWindowOwnerPID];
NSString* appName = windowInfo[(id)kCGWindowOwnerName];
NSLog(@"windowInfo get Fail pid:%lu appName:%@", pid.integerValue, appName);
}
}
CFRelease(windowList);
if (numberOfWindows == numberOfWindowsWithInfoGet) {
return YES;
} else {
return NO;
}
}
return YES;
}