mac开发-10.15检测屏幕录制权限

在Mac os 10.15之后,屏幕录制权限需要获取才能正确录屏,否则只能录制桌面背景以及自身app的影像。即可以截屏,但截不到其他app的内容。

文章目录

  • 屏幕录制权限检测
  • 屏幕录制授权申请
    • CGWindowListCreateImage
  • 隐私页面跳转
  • 清除某个App的权限记录
  • 清除某个隐私权限的全部内容
  • 遇到的问题

屏幕录制权限检测

对于Mac os 10.15的屏幕录制权限检测,使用如下方法为最佳:

- (BOOL)canRecordScreen
{
    if (@available(macOS 10.15, *)) {
        CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
        NSUInteger numberOfWindows = CFArrayGetCount(windowList);
        NSUInteger numberOfWindowsWithName = 0;
        for (int idx = 0; idx < numberOfWindows; idx++) {
            NSDictionary *windowInfo = (NSDictionary *)CFArrayGetValueAtIndex(windowList, idx);
            NSString *windowName = windowInfo[(id)kCGWindowName];
            if (windowName) {
                numberOfWindowsWithName++;
            } else {
                //no kCGWindowName detected -> not enabled
                break; //breaking early, numberOfWindowsWithName not increased
            }

        }
        CFRelease(windowList);
        return numberOfWindows == numberOfWindowsWithName;
    }
    return YES;
}

另外一种方法是下面这种?,在权限没有设置的时候没问题,但是在权限设置后,会导致mac os 10.15下的系统崩溃,直接回到登陆界面。所以没有使用这个

- (BOOL)canRecord{
    CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID() , 1, 1, kCVPixelFormatType_32ABGR, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef  _Nullable frameSurface, CGDisplayStreamUpdateRef  _Nullable updateRef) {
        
    });
    
    BOOL canRecord = stream != NULL;
    if (stream) {
        CFRelease(stream);
    }
    
    NSLog(@"canRecord : %ld",canRecord);
    return canRecord;
}

屏幕录制授权申请

通过截屏都可以向系统获取权限

CGWindowListCreateImage

- (void)showScreenRecordingPrompt{
  
  /* macos 10.14 and lower do not require screen recording permission to get window titles */
  if(@available(macos 10.15, *)) {
    /*
     To minimize the intrusion just make a 1px image of the upper left corner
     This way there is no real possibilty to access any private data
     */
    CGImageRef c = CGWindowListCreateImage(
                                                    CGRectMake(0, 0, 1, 1),
                                                    kCGWindowListOptionOnScreenOnly,
                                                    kCGNullWindowID,
                                                    kCGWindowImageDefault);
  
      CFRelease(screenshot);

}

截取主屏幕全部的内容

CGRect mainRect = CGDisplayBounds(CGMainDisplayID());
CGImageRef desktopImage = CGWindowListCreateImage(mainRect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageBestResolution | kCGWindowImageShouldBeOpaque);
NSImage* image = [[NSImage alloc]initWithCGImage:desktopImage size:_screenAsBtn.frame.size];
CGImageRelease(desktopImage);

截取某个子程序的图片

[_windowList removeAllObjects];
CFArrayRef windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray *windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray));
for(NSMutableDictionary* dic in windows){
    NSString* layerStr = [dic objectForKey:(__bridge id)kCGWindowLayer];
    CGRect bounds;
    CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[dic objectForKey:@"kCGWindowBounds"], &bounds);
    NSRectFromCGRect(bounds);
    if ([layerStr intValue] == 0 &&(bounds.size.width>10 && bounds.size.height>10)) {
        [_windowList addObject:dic];
    }
}
CFRelease(windowListArray);
//下面是for循环中内容,取每张图片
NSMutableDictionary* entry = [_windowList objectAtIndex:i];
int ownerPID = [[entry objectForKey:(__bridge id)kCGWindowNumber] intValue];
NSString* name =[entry objectForKey:(__bridge id)kCGWindowName];

NSString* owerName = [entry objectForKey:(__bridge id)kCGWindowOwnerName];
CGImageRef imageRef = CGWindowListCreateImage(CGRectNull,  kCGWindowListOptionIncludingWindow, ownerPID, kCGWindowImageShouldBeOpaque);
NSImage* image = [[NSImage alloc]initWithCGImage:imageRef size:NSZeroSize];
CGImageRelease(imageRef);

隐私页面跳转

- (void)openSetting{
    NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture";
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
}

清除某个App的权限记录

使用tccutil reset All com.xxx.xxx来清除,com.xxx.xxx为bundle id


清除某个隐私权限的全部内容

重置摄像头访问: tccutil reset Camera
重置麦克风访问: tccutil reset Microphone
重置屏幕录制:tccutil reset ScreenCapture


遇到的问题

遇到权限一直要获取,获取后提示关闭该程序,进入程序后,又需要获取的死循环。
这里我重启mac就好了,不知道是10.15系统原因否。


参考文章:
1.https://blog.csdn.net/lovechris00/article/details/96979960
2.https://xbuba.com/questions/56597221

你可能感兴趣的:(Mac开发)